chore: align ark-suac app and refresh appstore zip
This commit is contained in:
@@ -18,6 +18,7 @@ Fokus: korrekthet, låg risk och underhållbarhet.
|
|||||||
- Compose ska ha giltig top-level `name` (gemener + bindestreck).
|
- Compose ska ha giltig top-level `name` (gemener + bindestreck).
|
||||||
- Om `container_name` används måste den vara max 32 tecken och bara innehålla `0-9`, `a-z`, `A-Z`, `_`, `-`.
|
- Om `container_name` används måste den vara max 32 tecken och bara innehålla `0-9`, `a-z`, `A-Z`, `_`, `-`.
|
||||||
- Endast `.yaml` används i repot (aldrig `.yml`).
|
- Endast `.yaml` används i repot (aldrig `.yml`).
|
||||||
|
- Swap-filer (t.ex. `*.swp`, `*.swo`) ska alltid ignoreras och får aldrig committas.
|
||||||
|
|
||||||
## 3) Säkerhetsbaseline (Compose)
|
## 3) Säkerhetsbaseline (Compose)
|
||||||
|
|
||||||
|
|||||||
@@ -54,8 +54,8 @@ x-casaos:
|
|||||||
- arm64
|
- arm64
|
||||||
main: app
|
main: app
|
||||||
category: phirna
|
category: phirna
|
||||||
author: Zima Apps Team
|
author: Joachim Friberg
|
||||||
developer: example
|
developer: Joachim Friberg
|
||||||
icon: https://cdn.simpleicons.org/docker
|
icon: https://cdn.simpleicons.org/docker
|
||||||
tagline:
|
tagline:
|
||||||
en_US: Replace with a short one-line value proposition
|
en_US: Replace with a short one-line value proposition
|
||||||
|
|||||||
@@ -0,0 +1,124 @@
|
|||||||
|
# ARK: Survival Ascended Server
|
||||||
|
|
||||||
|
ARK: Survival Ascended dedicated server container for ZimaOS.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This app provides a dedicated server for ARK: Survival Ascended, allowing you to host your own game server with automatic updates and remote administration capabilities.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Automatic Updates**: Server files are automatically updated on startup
|
||||||
|
- **Cluster Support**: Configure multiple servers to work together
|
||||||
|
- **Remote Administration**: RCON access for server management
|
||||||
|
- **Customizable**: Adjust game parameters, player limits, and maps
|
||||||
|
- **Secure by Default**: Runs with minimal privileges and capabilities
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Ports
|
||||||
|
|
||||||
|
- **7777/udp**: Game port for player connections
|
||||||
|
- **27020/tcp**: RCON port for remote server administration
|
||||||
|
|
||||||
|
### Volumes
|
||||||
|
|
||||||
|
All volumes are mounted under `/DATA/AppData/ark-survival-ascended/`:
|
||||||
|
|
||||||
|
- `steam`: Steam runtime files
|
||||||
|
- `steamcmd`: SteamCMD installation
|
||||||
|
- `server-files`: ARK server files and save data
|
||||||
|
- `cluster-shared`: Shared data for cluster setups
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
- `TZ`: Timezone (default: Europe/Stockholm)
|
||||||
|
- `ASA_START_PARAMS`: Server start parameters and map configuration
|
||||||
|
- `ENABLE_DEBUG`: Set to "1" to enable debug mode (prevents server startup)
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
### Baseline Security
|
||||||
|
|
||||||
|
- Runs as non-root user `gameserver`
|
||||||
|
- All capabilities dropped (`cap_drop: ALL`)
|
||||||
|
- `no-new-privileges` security option enabled
|
||||||
|
- No privileged mode required
|
||||||
|
- No Docker socket access
|
||||||
|
|
||||||
|
### Data Persistence
|
||||||
|
|
||||||
|
All game data, including server files, save games, and configuration, is persisted in the bound volumes. The container will automatically download and update server files on startup.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### First Start
|
||||||
|
|
||||||
|
1. Install the app through ZimaOS App Store
|
||||||
|
2. Configure desired map and settings via `ASA_START_PARAMS`
|
||||||
|
3. Start the container - first startup will download ~11GB of server files
|
||||||
|
4. Connect to your server via the ARK game client
|
||||||
|
|
||||||
|
### Map Configuration
|
||||||
|
|
||||||
|
Change the map by modifying `ASA_START_PARAMS`. Example maps:
|
||||||
|
|
||||||
|
- `TheIsland_WP` (default)
|
||||||
|
- `ScorchedEarth_WP`
|
||||||
|
- `Ragnarok_WP`
|
||||||
|
- `Valguero_WP`
|
||||||
|
|
||||||
|
### Cluster Setup
|
||||||
|
|
||||||
|
For multi-server clusters:
|
||||||
|
|
||||||
|
1. Use the same `clusterid` parameter for all servers
|
||||||
|
2. Share the `cluster-shared` volume between containers
|
||||||
|
3. Configure different ports for each server instance
|
||||||
|
|
||||||
|
### Remote Administration
|
||||||
|
|
||||||
|
Connect to RCON on port 27020 using tools like:
|
||||||
|
|
||||||
|
- [ARK Server API](https://ark-server-api.com/)
|
||||||
|
- [Battlemetrics RCON](https://www.battlemetrics.com/rcon)
|
||||||
|
- Command line: `nc hostname 27020`
|
||||||
|
|
||||||
|
## Performance Requirements
|
||||||
|
|
||||||
|
- **RAM**: ~13GB per server instance
|
||||||
|
- **Disk**: ~11GB for server files + space for save games
|
||||||
|
- **CPU**: Modern multi-core processor recommended
|
||||||
|
|
||||||
|
## Updates
|
||||||
|
|
||||||
|
Server files are automatically updated on container startup. To update the container image itself, pull the new version through ZimaOS.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Server Not Visible
|
||||||
|
|
||||||
|
- Verify port 7777/udp is properly forwarded
|
||||||
|
- Check firewall settings
|
||||||
|
- Ensure `ASA_START_PARAMS` includes `?listen` parameter
|
||||||
|
|
||||||
|
### Connection Timeouts
|
||||||
|
|
||||||
|
- Verify your network configuration
|
||||||
|
- Check that UDP traffic is not being blocked
|
||||||
|
- Ensure the server has completed initialization (can take several minutes)
|
||||||
|
|
||||||
|
### Debug Mode
|
||||||
|
|
||||||
|
Set `ENABLE_DEBUG=1` to prevent server startup and investigate container issues.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Upstream Repository](https://github.com/mschnitzer/asa-linux-server)
|
||||||
|
- [ARK Official Website](https://survivetheark.com/)
|
||||||
|
- [SteamCMD Documentation](https://developer.valvesoftware.com/wiki/SteamCMD)
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
For issues specific to this ZimaOS integration, please contact the Zima Apps Team.
|
||||||
|
For game server issues, refer to the upstream repository or ARK official support.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
root/usr/share/proton/GE-Proton8-21.tar.gz filter=lfs diff=lfs merge=lfs -text
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
.PHONY: prepare build build-development build-beta load
|
||||||
|
|
||||||
|
GLOBAL_BUILD_DIR = /tmp/.kiwi-build-results
|
||||||
|
TARGET_DIR = $(GLOBAL_BUILD_DIR)/ark-survival-ascended-linux-container-image
|
||||||
|
|
||||||
|
prepare:
|
||||||
|
- sudo rm -rf $(TARGET_DIR)
|
||||||
|
- mkdir -p $(GLOBAL_BUILD_DIR)
|
||||||
|
|
||||||
|
build: prepare
|
||||||
|
- sudo kiwi-ng --profile stable --color-output --debug system build --target-dir $(TARGET_DIR) --description .
|
||||||
|
|
||||||
|
build-development: prepare
|
||||||
|
- sudo kiwi-ng --profile development --color-output --debug system build --target-dir $(TARGET_DIR) --description .
|
||||||
|
|
||||||
|
build-beta: prepare
|
||||||
|
- sudo kiwi-ng --profile beta --color-output --debug system build --target-dir $(TARGET_DIR) --description .
|
||||||
|
|
||||||
|
load:
|
||||||
|
- sudo docker load -i $(TARGET_DIR)/*.xz
|
||||||
@@ -0,0 +1,592 @@
|
|||||||
|
# ARK: Survival Ascended - Dedicated Linux Server - Docker Image
|
||||||
|
|
||||||
|
This repository provides a step by step guide for Linux administrators to host ARK: Survival Ascended servers on Linux using a docker image.
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
* [Hardware Requirements](#hardware-requirements)
|
||||||
|
* [Installation](#installation)
|
||||||
|
* [Install Docker & Docker Compose](#1-install-docker--docker-compose)
|
||||||
|
* [Start docker daemon](#2-start-docker-daemon)
|
||||||
|
* [Create the Docker Compose config](#3-create-the-docker-compose-config)
|
||||||
|
* [First server start](#4-first-server-start)
|
||||||
|
* [Server configuration](#5-server-configuration)
|
||||||
|
* [Changing the start parameters AND the player limit](#6-changing-the-start-parameters-and-the-player-limit)
|
||||||
|
* [Port forwarding?](#port-forwarding)
|
||||||
|
* [Changing the game port and RCON port](#changing-the-game-port-and-rcon-port)
|
||||||
|
* [Start/Restart/Stop](#startrestartstop)
|
||||||
|
* [Server Administration](#server-administration)
|
||||||
|
* [Debug Mode](#debug-mode)
|
||||||
|
* [Applying server updates](#applying-server-updates)
|
||||||
|
* [Daily restarts](#daily-restarts)
|
||||||
|
* [Executing RCON commands](#executing-rcon-commands)
|
||||||
|
* [Setting up a second server / cluster](#setting-up-a-second-server--cluster)
|
||||||
|
* [Adding Mods](#adding-mods)
|
||||||
|
* [Adding Mod Maps](#adding-mod-maps)
|
||||||
|
* [Adding Plugins](#adding-plugins)
|
||||||
|
* [Map Names](#map-names)
|
||||||
|
* [Updating the Container Image](#updating-the-container-image)
|
||||||
|
* [Common Issues](#common-issues)
|
||||||
|
* [Server is not visible in server browser](#server-is-not-visible-in-server-browser)
|
||||||
|
* [Addressing "Connection Timeout" issues](#addressing-connection-timeout-issues)
|
||||||
|
* [Your server has multiple IPv4 addresses](#your-server-has-multiple-ipv4-addresses)
|
||||||
|
* [Debugging with curl](#debugging-with-curl)
|
||||||
|
* [How to customize your routing?](#how-to-customize-your-routing)
|
||||||
|
* [Making your iptable rules persistent](#making-your-iptable-rules-persistent)
|
||||||
|
* [Found an Issue or Bug?](#found-an-issue-or-bug)
|
||||||
|
* [Credits](#credits)
|
||||||
|
|
||||||
|
## Hardware Requirements
|
||||||
|
|
||||||
|
The hardware requirements might change over time, but as of today you can expect:
|
||||||
|
|
||||||
|
* ~13 GB RAM usage per server instance
|
||||||
|
* ~11 GB disk space (the server files alone, without any savegames)
|
||||||
|
|
||||||
|
I cannot tell you what CPU to use, as I didn't do any testing on this, but this is the hardware I'm running one ASA server on:
|
||||||
|
|
||||||
|
* Intel Xeon E3-1275v5
|
||||||
|
* 2x SSD M.2 NVMe 512 GB
|
||||||
|
* 4x RAM 16384 MB DDR4 ECC
|
||||||
|
|
||||||
|
The server runs next to other services and it runs pretty well.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Required Linux experience: **Beginner**
|
||||||
|
|
||||||
|
In theory, you can use these steps on any Linux system where Docker is installed. It has been tested with:
|
||||||
|
|
||||||
|
* openSUSE Leap 15.6 (>= 16.0 won't work due to missing 32bit support)
|
||||||
|
* Debian 12 (bookworm)
|
||||||
|
* **NOT WORKING:** Ubuntu 22.04.x LTS (Jammy Jellyfish) [As of March 28th 2025, a recent distro update causes the container to have a constant high CPU usage, well beyond 400% and the server won't launch. Use Ubuntu 24.04.x if you can]
|
||||||
|
* Ubuntu 24.04.1 (Noble Numbat)
|
||||||
|
|
||||||
|
You need to be root user (`su root`) to perform these steps, but don't worry, the ASA server itself will run rootless.
|
||||||
|
|
||||||
|
### 1. Install Docker & Docker Compose
|
||||||
|
|
||||||
|
#### openSUSE Leap 15.6:
|
||||||
|
|
||||||
|
```
|
||||||
|
zypper in -y docker docker-compose
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Debian 12
|
||||||
|
|
||||||
|
It is recommended to install the docker engine from Docker's official repository. Follow the instructions in [this guide](https://docs.docker.com/engine/install/debian/#install-using-the-repository)
|
||||||
|
and refer to the "Install using the apt repository" section.
|
||||||
|
|
||||||
|
#### Ubuntu (24.04.x):
|
||||||
|
|
||||||
|
The docker engine is not part of the official Ubuntu 24.x repositories, thus you need to install it from the Docker's repository instead. Please refer to
|
||||||
|
[this guide](https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository) and follow the steps outlined in the "Install using the apt repository" section.
|
||||||
|
|
||||||
|
### 2. Start docker daemon
|
||||||
|
|
||||||
|
```
|
||||||
|
systemctl start docker
|
||||||
|
systemctl enable docker
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Create the Docker Compose config
|
||||||
|
|
||||||
|
Create a directory called `asa-server` wherever you like and download [my docker-compose.yml](https://github.com/mschnitzer/ark-survival-ascended-linux-container-image/blob/main/docker-compose.yml) example.
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir asa-server
|
||||||
|
cd asa-server
|
||||||
|
wget https://raw.githubusercontent.com/mschnitzer/ark-survival-ascended-linux-container-image/main/docker-compose.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. First server start
|
||||||
|
|
||||||
|
Now start the server for the first time. It will install Steam, Proton, and downloads the ARK: Survival Ascended server files.
|
||||||
|
|
||||||
|
Go to the directory of your `docker-compose.yml` file and execute the following command:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
It will download my docker image and then spins up a container called `asa-server-1` (defined in `docker-compose.yml`). You can follow the installation and the start of your server by running:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker logs -f asa-server-1
|
||||||
|
```
|
||||||
|
|
||||||
|
(Note: You can safely run `CTRL + C` to exit the log window again without causing the server to stop)
|
||||||
|
|
||||||
|
Once the log shows the following line:
|
||||||
|
|
||||||
|
```
|
||||||
|
Starting the ARK: Survival Ascended dedicated server...
|
||||||
|
```
|
||||||
|
|
||||||
|
... the server should be reachable and discoverable through the server browser in ~2-5 minutes.
|
||||||
|
|
||||||
|
The server name is randomly generated upon the first start. Please execute the following command to see under which name the server is discoverable in the server browser:
|
||||||
|
```
|
||||||
|
docker exec asa-server-1 cat server-files/ShooterGame/Saved/Config/WindowsServer/GameUserSettings.ini | grep SessionName
|
||||||
|
```
|
||||||
|
|
||||||
|
If the command fails in execution and reports an `No such file or directory` error, just wait some more minutes and it should eventually work. Once the command executed successfully, it should output something like this:
|
||||||
|
```
|
||||||
|
SessionName=ARK #334850
|
||||||
|
```
|
||||||
|
|
||||||
|
Now try to find the server by its name. Just search in the "Unofficial" section in ASA for the number of the server. In my case it is `334850`. If you are not able to connect to it right away, wait up to 5 more minutes and
|
||||||
|
try it again. If it's still not possible, [open an issue on GitHub](https://github.com/mschnitzer/ark-survival-ascended-linux-container-image/issues/new) to get help.
|
||||||
|
|
||||||
|
Once confirmed that you are able to connect, stop the server again:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker stop asa-server-1
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Server configuration
|
||||||
|
|
||||||
|
The `docker-compose.yml` config defines three docker volumes, which serve as a storage for your server files, Steam, and Proton. They are directly mounted to the docker container and can be edited outside of the container. The
|
||||||
|
location of these volumes is `/var/lib/docker/volumes`. If you followed the steps 1:1, then you should find the following directories at that location:
|
||||||
|
|
||||||
|
```
|
||||||
|
asa-server_cluster-shared/
|
||||||
|
asa-server_server-files-1/
|
||||||
|
asa-server_steam-1/
|
||||||
|
asa-server_steamcmd-1/
|
||||||
|
```
|
||||||
|
|
||||||
|
The prefix `asa-server` is defined by the directory name of your `docker-compose.yml` file.
|
||||||
|
|
||||||
|
You can ignore `asa-server_steam-1` and `asa-server_steamcmd-1`, these volumes are being used by the container to avoid setting up `Steam` and `steamcmd` on every launch again. Server files including config files are stored at `asa-server_server-files-1`. `asa-server_cluster-shared` provides support for server clusters, so that survivors can travel between your servers with their characters and dinos.
|
||||||
|
|
||||||
|
The `GameUserSettings.ini` and `Game.ini` file can be found at `/var/lib/docker/volumes/asa-server_server-files-1/_data/ShooterGame/Saved/Config/WindowsServer`. The `Game.ini` file is not there by default, so you might want to create it yourself.
|
||||||
|
|
||||||
|
You don't need to worry about file permissions. The `docker-compose.yml` is running a container before starting the ASA server and adjusts the file permissions to `25000:25000`, which is the user id and group id the server starts with. These ids are not bound to any user on your system and that's fine and not an issue.
|
||||||
|
|
||||||
|
### 6. Changing the start parameters AND the player limit
|
||||||
|
|
||||||
|
Start parameters are defined in the `docker-compose.yml`:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
...
|
||||||
|
environment:
|
||||||
|
- ASA_START_PARAMS=TheIsland_WP?listen?Port=7777?RCONPort=27020?RCONEnabled=True -WinLiveMaxPlayers=50
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Please note:
|
||||||
|
* The value before `?listen` is the name of the map the server launches with. ([See all official map names](#map-names))
|
||||||
|
* Please do not remove `?listen` from the parameters, otherwise the server is not binding ports
|
||||||
|
* `?Port=` is the server port players connect to
|
||||||
|
* `?RCONPort=` is the port of the RCON server that allows remote administration of the server
|
||||||
|
* The player limit is set by `-WinLiveMaxPlayers`. Please note that for ASA servers, editing the player limit via `GameUserSettings.ini` is not working.
|
||||||
|
|
||||||
|
## Port forwarding?
|
||||||
|
|
||||||
|
There should not be the need to forward any ports if your server runs in a public cloud. This is because docker configures `iptables` by itself. In a home setup, where a router is in between, it is very likely that you need to forward ports.
|
||||||
|
|
||||||
|
In any case, you ONLY need to forward the following ports:
|
||||||
|
|
||||||
|
```
|
||||||
|
7777 (UDP only - This is the game port to allow players to connect to the server)
|
||||||
|
27020 (TCP only - This is the port to connect through RCON and is therefore optional to forward)
|
||||||
|
```
|
||||||
|
|
||||||
|
As of today, ASA does no longer offer a way to query the server, so there's no query port and you won't be able to find your server through the Steam server browser, only via the ingame browser.
|
||||||
|
|
||||||
|
## Changing the game port and RCON port
|
||||||
|
|
||||||
|
You already learned that ports are defined by `ASA_START_PARAMS` in the `docker-compose.yml` file. This just tells the ASA server what ports to bind.
|
||||||
|
As a first step for port changes adjust the start parameters accordingly.
|
||||||
|
|
||||||
|
E. g. if you want to change the game port from `7777` to `7755` your new start parameters would look like this:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
...
|
||||||
|
environment:
|
||||||
|
- ASA_START_PARAMS=TheIsland_WP?listen?Port=7755?RCONPort=27020?RCONEnabled=True -WinLiveMaxPlayers=50 -clusterid=default -ClusterDirOverride="/home/gameserver/cluster-shared"
|
||||||
|
- ENABLE_DEBUG=0
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
But this alone is not enough and you need to apply the following changes as well.
|
||||||
|
|
||||||
|
Open the `docker-compose.yml` file again and edit the lines where the container ports are defined:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
...
|
||||||
|
ports:
|
||||||
|
# Game port for player connections through the server browser
|
||||||
|
- 0.0.0.0:7777:7777/udp
|
||||||
|
# RCON port for remote server administration
|
||||||
|
- 0.0.0.0:27020:27020/tcp
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Adjust the port to your liking, but make sure that you change both numbers (the one before and after the `:`). Assuming the above game port changes to `7755` this would be the result:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
...
|
||||||
|
ports:
|
||||||
|
# Game port for player connections through the server browser
|
||||||
|
- 0.0.0.0:7755:7755/udp
|
||||||
|
# RCON port for remote server administration
|
||||||
|
- 0.0.0.0:27020:27020/tcp
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Now that your port changes are set, you have to recreate your container. Therefore you need to use `docker compose up -d` in order to apply your port changes.
|
||||||
|
|
||||||
|
|
||||||
|
## Start/Restart/Stop
|
||||||
|
|
||||||
|
To perform any of the actions, execute the following commands (you need to be in the directory of the `docker-compose.yml` file):
|
||||||
|
|
||||||
|
```
|
||||||
|
docker compose start asa-server-1
|
||||||
|
docker compose restart asa-server-1
|
||||||
|
docker compose stop asa-server-1
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also use the native docker commands, where you do not need to be in the directory of the `docker-compose.yml` file. However using this method would not check for changes in your `docker-compose.yml` file.
|
||||||
|
So in case you edited the `docker-compose.yml` file (e.g. because you adjusted the start parameters), you need to use `docker compose` commands instead.
|
||||||
|
```
|
||||||
|
docker start/restart/stop asa-server-1
|
||||||
|
```
|
||||||
|
|
||||||
|
## Server Administration
|
||||||
|
|
||||||
|
### Debug Mode
|
||||||
|
|
||||||
|
Sometimes you want to test something inside the container without starting the ASA server. The debug mode can be enabled by changing `- ENABLE_DEBUG=0` to `1` in the `docker-compose.yml` file.
|
||||||
|
Once done, the result will look like this:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
...
|
||||||
|
version: "3.3"
|
||||||
|
services:
|
||||||
|
asa-server-1:
|
||||||
|
container_name: asa-server-1
|
||||||
|
hostname: asa-server-1
|
||||||
|
entrypoint: "/usr/bin/start_server"
|
||||||
|
user: gameserver
|
||||||
|
image: "mschnitzer/asa-linux-server:latest"
|
||||||
|
environment:
|
||||||
|
- ASA_START_PARAMS=TheIsland_WP?listen?Port=7777?RCONPort=27020?RCONEnabled=True -WinLiveMaxPlayers=50
|
||||||
|
- ENABLE_DEBUG=1
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Now run `docker compose up -d` and the container will just start without launching the server or validating server files.
|
||||||
|
|
||||||
|
Check if the container launched in debug mode by running `docker logs -f asa-server-1` and check whether it's saying "Entering debug mode...". If that's the case, you are good.
|
||||||
|
|
||||||
|
You can enter the shell of your server by running
|
||||||
|
|
||||||
|
```
|
||||||
|
docker exec -ti asa-server-1 bash
|
||||||
|
```
|
||||||
|
|
||||||
|
If you need root access run
|
||||||
|
|
||||||
|
```
|
||||||
|
docker exec -ti -u root asa-server-1 bash
|
||||||
|
```
|
||||||
|
|
||||||
|
### Applying server updates
|
||||||
|
|
||||||
|
Updates will be automatically downloaded or applied once you restart the container with ...
|
||||||
|
|
||||||
|
```
|
||||||
|
docker restart asa-server-1
|
||||||
|
```
|
||||||
|
|
||||||
|
It is totally possible that after a restart and applying all updates, the client is still one or more versions ahead. This is because Wildcard does sometimes run client-only updates, since not all
|
||||||
|
updates are affecting the server software. This is not a problem at all. As long as you can connect to your server, everything is fine. The server software checks for incompatible client
|
||||||
|
versions anyway.
|
||||||
|
|
||||||
|
In general you can check when the latest server update was published by Wildcard, by checking [this link](https://steamdb.info/app/2430930/depots/). The section mentioning the last update of the `public` branch
|
||||||
|
tells you when the last update was rolled out for the server software.
|
||||||
|
|
||||||
|
If you have any doubts on this, open a GitHub issue.
|
||||||
|
|
||||||
|
### Daily restarts
|
||||||
|
|
||||||
|
As `root` user of your server (or any other user that is member of the `docker` group) open your crontab configuration:
|
||||||
|
|
||||||
|
```
|
||||||
|
crontab -e
|
||||||
|
```
|
||||||
|
|
||||||
|
Add the following lines to it:
|
||||||
|
```
|
||||||
|
30 3 * * * docker exec asa-server-1 asa-ctrl rcon --exec 'serverchat Server restart in 30 minutes'
|
||||||
|
50 3 * * * docker exec asa-server-1 asa-ctrl rcon --exec 'serverchat Server restart in 10 minutes'
|
||||||
|
57 3 * * * docker exec asa-server-1 asa-ctrl rcon --exec 'serverchat Server restart in 3 minutes'
|
||||||
|
58 3 * * * docker exec asa-server-1 asa-ctrl rcon --exec 'saveworld'
|
||||||
|
0 4 * * * docker restart asa-server-1
|
||||||
|
```
|
||||||
|
|
||||||
|
Explanation:
|
||||||
|
* Line 1: Every day at 03:30am of your server's timezone, a message will be sent to all players announcing a restart in 30 minutes.
|
||||||
|
* Line 2: Every day at 03:50am of your server's timezone, a message will be sent to all players announcing a restart in 10 minutes.
|
||||||
|
* Line 3: Every day at 03:57am of your server's timezone, a message will be sent to all players announcing a restart in 3 minutes.
|
||||||
|
* Line 4: Every day at 03:58am of your server's timezone, the server saves the world before the restart happens.
|
||||||
|
* Line 5: Every day at 04:00am of your server's timezone, the ASA server gets restarted and installs pending updates from Steam.
|
||||||
|
|
||||||
|
Read more about the crontab syntax [here](https://www.adminschoice.com/crontab-quick-reference).
|
||||||
|
|
||||||
|
**NOTE:** The first 4 lines execute RCON commands, which requires you to have a working RCON setup. Please follow the instructions in section "[Executing RCON commands](#executing-rcon-commands)" to
|
||||||
|
ensure you can execute RCON commands.
|
||||||
|
|
||||||
|
### Executing RCON commands
|
||||||
|
|
||||||
|
You can run RCON commands by accessing the `rcon` subcommand of the `asa-ctrl` tool which is shipped with the container image. There's no need to enter your server password, IP, or RCON port manually. As long as
|
||||||
|
you have set your RCON password and port, either as a start parameter or in the `GameUserSettings.ini` file of your server, `asa-ctrl` is able to figure those details out by itself.
|
||||||
|
|
||||||
|
The following variables need to be present in `GameUserSettings.ini` under the `[ServerSettings]` section:
|
||||||
|
|
||||||
|
```
|
||||||
|
RCONEnabled=True
|
||||||
|
ServerAdminPassword=mysecretpass
|
||||||
|
RCONPort=27020
|
||||||
|
```
|
||||||
|
|
||||||
|
**NOTE:** There can be issues setting `ServerAdminPassword` as command line option. I'd suggest to set it in the `GameUserSettings.ini` file only.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker exec -t asa-server-1 asa-ctrl rcon --exec 'saveworld'
|
||||||
|
```
|
||||||
|
|
||||||
|
**NOTE:** As opposed to ingame cheat commands, you must not put `admincheat` or `cheat` in front of the command.
|
||||||
|
|
||||||
|
## Setting up a second server / cluster
|
||||||
|
|
||||||
|
Setting up a second server is quite easy and you can easily add more if you want (given that your hardware is capable of running multiple instances). There's already a definition for a second server in the `docker-compose.yml` file,
|
||||||
|
but the definition is commented out by a leading `#`. If you remove these `#`, and run `docker compose up -d` again, then the second server should start and it will listen on the game port `7778` and the query port `27021`. Please note that
|
||||||
|
the server files, as well as Steam, and steamcmd will be downloaded again and the first start can take a while.
|
||||||
|
|
||||||
|
You can edit the start parameters in the same way like for the first server and the files of the second server are located at the same location, except that the second server has its suffix changed from `-1` to `-2`. The directories will therefore,
|
||||||
|
named like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
asa-server_server-files-2/
|
||||||
|
asa-server_steam-2/
|
||||||
|
asa-server_steamcmd-2/
|
||||||
|
```
|
||||||
|
|
||||||
|
That's it! Your second server is now running in a cluster setup. This means that travelling between your servers is possible through Obelisks. If you do not want players to travel between your servers, you need to remove the `-clusterid` option
|
||||||
|
from the start parameters. It's advised to change the `-clusterid` parameter for all of your servers to a random string and keep it secret (e.g. `-clusterid=aSM42F6PLaPk` as opposed to `-clusterid=default`). The reason for that is that you will
|
||||||
|
end up seeing also other servers from the community that use `default` as their `clusterid`. If you only want players to travel between your own servers, then the `clusterid` must be different.
|
||||||
|
|
||||||
|
If you want to spin up more servers, you need to add more entries to the `docker-compose.yml` file. The following sections need to be edited: `services` and `volumes`. Make sure that you adjust all suffixes and replace them with a new one
|
||||||
|
(e.g. `-3` now) for the newly added entries.
|
||||||
|
|
||||||
|
## Adding Mods
|
||||||
|
|
||||||
|
Mods can be added by adjusting the `docker-compose.yml` file and adding a `-mods` option to the start parameters.
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
|
||||||
|
```
|
||||||
|
[...]
|
||||||
|
- ASA_START_PARAMS=TheIsland_WP?listen?Port=7777?RCONPort=27020?RCONEnabled=True -WinLiveMaxPlayers=50 -mods=12345,67891
|
||||||
|
[...]
|
||||||
|
```
|
||||||
|
|
||||||
|
Once done, restart the server using `docker compose up -d`. It might take longer until the server comes up, because the server has to download the mods first.
|
||||||
|
|
||||||
|
Mod IDs are usually somewhere listed on the mod page of a mod on curseforge.com.
|
||||||
|
|
||||||
|
### Adding Mod Maps
|
||||||
|
|
||||||
|
Search for a map on curseforge.com and find out what mod id the map has and what the map name is. For the map [Svartalfheim](https://www.curseforge.com/ark-survival-ascended/mods/svartalfheim) the map name
|
||||||
|
is `Svartalfheim_WP` and the mod id is `893657`.
|
||||||
|
|
||||||
|
Once you found out the information you need, you need to adjust your start parameters in the `docker-compose.yml` file and add the map name, as well as the `-mods` option.
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
|
||||||
|
```
|
||||||
|
[...]
|
||||||
|
- ASA_START_PARAMS=Svartalfheim_WP?listen?Port=7777?RCONPort=27020?RCONEnabled=True -WinLiveMaxPlayers=50 -mods=893657
|
||||||
|
[...]
|
||||||
|
```
|
||||||
|
|
||||||
|
Restart your server using `docker compose up -d`. It may take a while, as the server has to download the map, so be patient.
|
||||||
|
|
||||||
|
## Adding Plugins
|
||||||
|
|
||||||
|
Plugin support was introduced by version 1.4.0 of this container image. So make sure that you updated to the latest version of the container image or to version 1.4.0 as described [here](#updating-the-container-image).
|
||||||
|
|
||||||
|
There's a project ([see here](https://gameservershub.com/forums/resources/ark-survival-ascended-serverapi-crossplay-supported.683/)) that allows you to load plugins on your server (e.g. permission handling). To install the plugin loader, please visit [gameservershub.com](https://gameservershub.com/forums/resources/ark-survival-ascended-serverapi-crossplay-supported.683/) and refer to the "ServerAPI Installation Steps" section and download the zip archive. A `gameservershub.com` account is required in order to download the plugin loader.
|
||||||
|
|
||||||
|
When the download of the zip archive is completed, follow these steps to install the plugin loader:
|
||||||
|
|
||||||
|
1. Make sure that you launched the ASA server at least once without the plugin loader.
|
||||||
|
2. Stop the ASA server container by running `docker stop asa-server-1`
|
||||||
|
3. Enter the server files binary directory as `root` user: `cd /var/lib/docker/volumes/asa-server_server-files-1/_data/ShooterGame/Binaries/Win64`
|
||||||
|
4. Place the downloaded zip archive in that directory (the name of the archive must start with `AsaApi_`). Do not unzip the content.
|
||||||
|
5. Restart your server using `docker compose up -d`
|
||||||
|
|
||||||
|
The installation happens automatically by the container start script. You can follow the installation process by running `docker logs -f asa-server-1`. Once the log says "Detected ASA Server API loader. Launching server through AsaApiLoader.exe",
|
||||||
|
the installation is complete. In the following log lines your should see the start process of the plugin loader.
|
||||||
|
|
||||||
|
How to install plugins is described on gameservershub.com, from which you obtained the plugin loader. Please refer to their guide instead.
|
||||||
|
|
||||||
|
## Map Names
|
||||||
|
|
||||||
|
This is a list of all official map names with their map id. The map id is used as start parameter in the `docker-compose.yml` file. ([click](#6-changing-the-start-parameters-and-the-player-limit))
|
||||||
|
|
||||||
|
| Map Name | Map ID (for the start parameter) |
|
||||||
|
| ------------- | ------------- |
|
||||||
|
| The Island | TheIsland_WP |
|
||||||
|
| Scorched Earth | ScorchedEarth_WP |
|
||||||
|
| The Center | TheCenter_WP |
|
||||||
|
| Aberration | Aberration_WP |
|
||||||
|
| Extinction | Extinction_WP |
|
||||||
|
| Ragnarok | Ragnarok_WP |
|
||||||
|
| Astraeos | Astraeos_WP |
|
||||||
|
| Valguero | Valguero_WP |
|
||||||
|
| Lost Colony | LostColony_WP |
|
||||||
|
|
||||||
|
**NOTE:** Mod Maps have their own id! ([click](#adding-mod-maps))
|
||||||
|
|
||||||
|
## Updating the Container Image
|
||||||
|
|
||||||
|
The container image will be updated from time to time. In general, we try to not break previous installations by an update, but to add certain features, it might be necessary to introduce backward incompatibilities.
|
||||||
|
The default `docker-compose.yml` file suggests to use the `latest` branch of the container image. If you want to stay on one specific version, you can force the container image to launch with that said version, by
|
||||||
|
changing `image: "mschnitzer/asa-linux-server:latest"` in your `docker-compose.yml` file (as outlined below) to whatever version suits you. A list of all versions can be
|
||||||
|
found [here](https://hub.docker.com/r/mschnitzer/asa-linux-server/tags).
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
If you want to stay on version `1.4.0` for your ASA server, you must change `image: "mschnitzer/asa-linux-server:latest"` to `image: "mschnitzer/asa-linux-server:1.4.0"`.
|
||||||
|
|
||||||
|
Even if you stay on branch `latest`, your container image won't be updated automatically if we roll out an update. You explicitly need to run `docker pull mschnitzer/asa-linux-server:latest` to obtain the newest version.
|
||||||
|
|
||||||
|
We strongly suggest to read through the [releases page](https://github.com/mschnitzer/ark-survival-ascended-linux-container-image/releases) of this repository to see what has changed between versions. If there's
|
||||||
|
a backward incompatibility being introduced, it will be mentioned there with an explanation what to change.
|
||||||
|
|
||||||
|
## Common Issues
|
||||||
|
|
||||||
|
### Server is not visible in server browser
|
||||||
|
|
||||||
|
If you cannot discover your server in the server browser, it's most likely due to at least one of the following reasons:
|
||||||
|
|
||||||
|
* Your server is still booting up, give it ~5 minutes
|
||||||
|
* You are not looking at the "Unofficial" server browser list
|
||||||
|
* Your filter settings in the server browser exclude your server
|
||||||
|
* You forgot clicking the "Show player server settings". ([view screenshot](https://raw.githubusercontent.com/mschnitzer/ark-survival-ascended-linux-container-image/main/assets/show-player-servers.jpg)) By default, only Nitrado servers are shown to players when searching for unofficial servers, unfortunately.
|
||||||
|
|
||||||
|
## Addressing "Connection Timeout" issues
|
||||||
|
|
||||||
|
First of all, try to connect through the ingame console to your server. In many cases this works, but only connecting through the server browser causes an issue. Try to run the command `open $IP:$PORT` and test whether you
|
||||||
|
can connect to it.
|
||||||
|
|
||||||
|
If that is NOT working and you are having a home setup and not a VPS cloud setup, make sure your ports are REALLY open. This needs to be configured on your router. The ports that need to be opened are listed above in this README.
|
||||||
|
Please refer to the documentation of your router how to configure port forwarding properly.
|
||||||
|
|
||||||
|
If you can connect to your server through the console command, but not via the sever browser, it is very likely that you are running into one of these issues:
|
||||||
|
|
||||||
|
### Your server has multiple IPv4 addresses
|
||||||
|
|
||||||
|
If your server has multiple IPv4 addresses and you bound your ASA server to one of the secondary ones, by default, docker routes your traffic always through your primary network interface, which would cause the server browser to list your
|
||||||
|
server under the wrong IP address.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
Your primary IP is: `255.255.300.300`
|
||||||
|
Your secondary one is: `255.255.400.400`
|
||||||
|
|
||||||
|
You adjusted the `docker-compose.yml` file in a way where it binds the ports on interface `255.255.400.400`. However, if your ASA server communicates with the internet and announces itself to the ASA server list, the ASA master server that manages the
|
||||||
|
server browser entries, would see the requests coming from `255.255.300.300` as this is your primary network interface.
|
||||||
|
|
||||||
|
This issue can be solved by forcing the traffic to be routed manually through your secondary network interface.
|
||||||
|
|
||||||
|
But before we start fixing it, you should make sure that this is really the issue.
|
||||||
|
|
||||||
|
#### Debugging with curl
|
||||||
|
|
||||||
|
1. Log in to the container `docker exec -ti -u root asa-server-1 bash`
|
||||||
|
2. Run `zypper --no-gpg-checks ref`
|
||||||
|
3. Install curl `zypper in -y curl`
|
||||||
|
4. Run `curl icanhazip.com` (`icanhazip.com` is a service that tells you from what ip address it received traffic from)
|
||||||
|
|
||||||
|
If the service responds with an IP that you have not assigned to the ASA server in the `docker-compose.yml` file, then it's very likely that this is the reason why you are getting a "Connection Timeout" error.
|
||||||
|
Please continue following the instructions below.
|
||||||
|
|
||||||
|
#### How to customize your routing?
|
||||||
|
|
||||||
|
You need to adjust the `docker-compose.yml` file and add `com.docker.network.bridge.enable_ip_masquerade: 'false'` to the `networks` section, so that it looks like this:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
networks:
|
||||||
|
asa-network:
|
||||||
|
attachable: true
|
||||||
|
driver: bridge
|
||||||
|
driver_opts:
|
||||||
|
com.docker.network.bridge.name: 'asanet'
|
||||||
|
com.docker.network.bridge.enable_ip_masquerade: 'false'
|
||||||
|
```
|
||||||
|
|
||||||
|
Now stop the ASA server if it's running:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker stop asa-server-1
|
||||||
|
```
|
||||||
|
|
||||||
|
Delete the docker network interface and the container, so that they can be recreated:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker rm asa-server-1
|
||||||
|
docker network rm asa-server_asa-network
|
||||||
|
```
|
||||||
|
|
||||||
|
Now run `docker compose up -d` from within the directory where your `docker-compose.yml` is located at.
|
||||||
|
|
||||||
|
Once done and the container is up again, inspect the network to find its subnet:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker network inspect asa-server_asa-network | grep Subnet
|
||||||
|
```
|
||||||
|
|
||||||
|
Now customize the routing of the container through `iptables`, where `$SUBNET` needs to be replaced with the subnet from the previous command (including the `/24` or `/16` - whatever it is in your case):
|
||||||
|
|
||||||
|
```
|
||||||
|
iptables -t nat -A POSTROUTING -s $SUBNET ! -o asanet -j SNAT --to-source $YOUR_SECONDARY_IP_USED_BY_ASA
|
||||||
|
```
|
||||||
|
|
||||||
|
Once done, connect to your container and test that the remote IP is the right one, by following the steps with `curl` again.
|
||||||
|
|
||||||
|
Now try to connect to your server through the server browser. If that is not solving your problem or if the IP is still the wrong one, open a GitHub issue. If it solves your problem, continue with the
|
||||||
|
next section to make the `iptables` adjustments persistent after reboot.
|
||||||
|
|
||||||
|
#### Making your iptable rules persistent
|
||||||
|
|
||||||
|
Changes to the `iptables` will get reverted after reboot. You can make them persistent by saving the current state:
|
||||||
|
|
||||||
|
```
|
||||||
|
iptables-save > /root/iptables
|
||||||
|
```
|
||||||
|
|
||||||
|
Now run `crontab -e` and add the following entry:
|
||||||
|
|
||||||
|
```
|
||||||
|
@reboot /bin/bash -c 'sleep 15 ; /usr/sbin/iptables-restore < /root/iptables'
|
||||||
|
```
|
||||||
|
|
||||||
|
Save the cronjob and test it by rebooting your system. You can test whether it has worked by following the `curl` steps from above again.
|
||||||
|
|
||||||
|
## Found an Issue or Bug?
|
||||||
|
|
||||||
|
Create a ticket on GitHub, I will do my best to fix it. Feel free to open a pull request as well.
|
||||||
|
|
||||||
|
## Credits
|
||||||
|
|
||||||
|
* Glorius Eggroll - For his version of Proton to run the ARK Windows binaries on Linux ([click](https://github.com/GloriousEggroll/proton-ge-custom))
|
||||||
|
* cdp1337 - For his Linux guide of installing Proton and running ARK on Linux ([click](https://github.com/cdp1337/ARKSurvivalAscended-Linux))
|
||||||
|
* tesfabpel - For his Valve RCON implementation in Ruby ([click](https://github.com/tesfabpel/srcon-rb))
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<image schemaversion="7.4" name="asa-linux-server">
|
||||||
|
<description type="system">
|
||||||
|
<author>Manuel Schnitzer</author>
|
||||||
|
<contact>github@mschnitzer.de</contact>
|
||||||
|
<specification>ARK: Survival Ascended - Dedicated Server (Linux)</specification>
|
||||||
|
</description>
|
||||||
|
<profiles>
|
||||||
|
<profile name="stable" description="building docker tag: latest"/>
|
||||||
|
<profile name="beta" description="building docker tag: beta"/>
|
||||||
|
<profile name="development" description="building docker tag: development"/>
|
||||||
|
</profiles>
|
||||||
|
<preferences>
|
||||||
|
<version>1.5.1</version>
|
||||||
|
<packagemanager>zypper</packagemanager>
|
||||||
|
<rpm-excludedocs>true</rpm-excludedocs>
|
||||||
|
<rpm-check-signatures>false</rpm-check-signatures>
|
||||||
|
<locale>en_US</locale>
|
||||||
|
<keytable>us</keytable>
|
||||||
|
</preferences>
|
||||||
|
<preferences profiles="stable">
|
||||||
|
<type image="docker">
|
||||||
|
<containerconfig tag="latest" workingdir="/home/gameserver" name="mschnitzer/asa-linux-server"/>
|
||||||
|
</type>
|
||||||
|
</preferences>
|
||||||
|
<preferences profiles="beta">
|
||||||
|
<type image="docker">
|
||||||
|
<containerconfig tag="beta" workingdir="/home/gameserver" name="mschnitzer/asa-linux-server"/>
|
||||||
|
</type>
|
||||||
|
</preferences>
|
||||||
|
<preferences profiles="development">
|
||||||
|
<type image="docker">
|
||||||
|
<containerconfig tag="development" workingdir="/home/gameserver" name="mschnitzer/asa-linux-server"/>
|
||||||
|
</type>
|
||||||
|
</preferences>
|
||||||
|
<users>
|
||||||
|
<user name="gameserver" password="" home="/home/gameserver" groups="gameserver" id="25000"/>
|
||||||
|
</users>
|
||||||
|
<repository type="rpm-md" alias="repo-oss" imageinclude="true">
|
||||||
|
<source path="http://cdn.opensuse.org/distribution/leap/16.0/repo/oss/x86_64"/>
|
||||||
|
</repository>
|
||||||
|
<packages type="image">
|
||||||
|
<package name="patterns-base-base"/>
|
||||||
|
<package name="glibc-locale-base"/>
|
||||||
|
<package name="timezone"/>
|
||||||
|
<!-- application dependencies: ASA -->
|
||||||
|
<package name="libgcc_s1-32bit"/>
|
||||||
|
<package name="python313"/>
|
||||||
|
<package name="wget"/>
|
||||||
|
<package name="tar"/>
|
||||||
|
<package name="libfreetype6"/>
|
||||||
|
<!-- application dependencies: ASA server api plugin loader -->
|
||||||
|
<package name="unzip"/>
|
||||||
|
<!-- application dependencies: asa-ctrl -->
|
||||||
|
<package name="ruby3.4"/>
|
||||||
|
<package name="ruby3.4-devel"/>
|
||||||
|
<package name="make"/>
|
||||||
|
<package name="gcc-c++"/>
|
||||||
|
</packages>
|
||||||
|
<packages type="image" profiles="development">
|
||||||
|
<package name="vim"/>
|
||||||
|
<package name="vim-data"/>
|
||||||
|
<package name="vim-data-common"/>
|
||||||
|
</packages>
|
||||||
|
<packages type="bootstrap">
|
||||||
|
<package name="udev"/>
|
||||||
|
<package name="filesystem"/>
|
||||||
|
<package name="glibc-locale"/>
|
||||||
|
<package name="cracklib-dict-small"/>
|
||||||
|
<package name="ca-certificates"/>
|
||||||
|
<package name="ca-certificates-mozilla"/>
|
||||||
|
</packages>
|
||||||
|
<packages type="delete">
|
||||||
|
<package name="dbus-1"/>
|
||||||
|
<package name="kbd"/>
|
||||||
|
<package name="kmod"/>
|
||||||
|
<package name="ncurses-utils"/>
|
||||||
|
<package name="pinentry"/>
|
||||||
|
<package name="udev"/>
|
||||||
|
<package name="glibc-locale"/>
|
||||||
|
<package name="systemd"/>
|
||||||
|
</packages>
|
||||||
|
<packages type="delete" profiles="stable,beta">
|
||||||
|
<package name="ruby3.4-devel"/>
|
||||||
|
<package name="make"/>
|
||||||
|
<package name="gcc-c++"/>
|
||||||
|
<package name="gcc15"/>
|
||||||
|
<package name="gcc15-c++"/>
|
||||||
|
<package name="libstdc++6-devel-gcc15"/>
|
||||||
|
</packages>
|
||||||
|
</image>
|
||||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 227 KiB |
@@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
rm -f /etc/localtime
|
||||||
|
zypper --gpg-auto-import-keys ref
|
||||||
|
|
||||||
|
groupmod -g 25000 gameserver
|
||||||
|
usermod -u 25000 gameserver
|
||||||
|
|
||||||
|
chmod 0755 /usr/bin/start_server
|
||||||
|
chmod 0755 /usr/bin/cli-asa-mods
|
||||||
|
|
||||||
|
# install ruby gems
|
||||||
|
cd /usr/share/asa-ctrl
|
||||||
|
bundle.ruby3.4
|
||||||
|
|
||||||
|
if [ "$kiwi_profiles" = "development" ]; then
|
||||||
|
# will be mounted to ease development
|
||||||
|
rm -r /usr/share/asa-ctrl
|
||||||
|
gem.ruby3.4 install byebug
|
||||||
|
else
|
||||||
|
chmod 0755 /usr/share/asa-ctrl/main.rb
|
||||||
|
fi
|
||||||
|
|
||||||
|
ln -s /usr/share/asa-ctrl/main.rb /usr/bin/asa-ctrl
|
||||||
|
|
||||||
|
# This fixes a warning with Proton. The warning confused some people, but it haven't had any effect on the ASA server.
|
||||||
|
echo "d5b7b5ed-1674-497d-ad98-7437a6543312" > /etc/machine-id
|
||||||
|
chmod 644 /etc/machine-id
|
||||||
|
|
||||||
|
exit 0
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
###
|
||||||
|
### THIS IS THE DEVELOPMENT COMPOSE FILE!
|
||||||
|
### You are most likely looking for the 'docker-compose.yml' file instead!
|
||||||
|
###
|
||||||
|
version: "3.3"
|
||||||
|
services:
|
||||||
|
asa-server-1:
|
||||||
|
container_name: asa-server-1
|
||||||
|
hostname: asa-server-1
|
||||||
|
entrypoint: "/usr/bin/start_server"
|
||||||
|
user: gameserver
|
||||||
|
image: "mschnitzer/asa-linux-server:development"
|
||||||
|
tty: true
|
||||||
|
environment:
|
||||||
|
- ASA_START_PARAMS=TheIsland_WP?listen?Port=7777?RCONPort=27020?RCONEnabled=True -WinLiveMaxPlayers=50 -clusterid=default -ClusterDirOverride="/home/gameserver/cluster-shared"
|
||||||
|
- ENABLE_DEBUG=0
|
||||||
|
ports:
|
||||||
|
# Game port for player connections through the server browser
|
||||||
|
- 0.0.0.0:7777:7777/udp
|
||||||
|
# RCON port for remote server administration
|
||||||
|
- 0.0.0.0:27020:27020/tcp
|
||||||
|
depends_on:
|
||||||
|
- set-permissions-1
|
||||||
|
volumes:
|
||||||
|
- steam-1:/home/gameserver/Steam:rw
|
||||||
|
- steamcmd-1:/home/gameserver/steamcmd:rw
|
||||||
|
- server-files-1:/home/gameserver/server-files:rw
|
||||||
|
- cluster-shared:/home/gameserver/cluster-shared:rw
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
- ./root/usr/share/asa-ctrl:/usr/share/asa-ctrl:rw
|
||||||
|
networks:
|
||||||
|
asa-network:
|
||||||
|
set-permissions-1:
|
||||||
|
entrypoint: "/bin/bash -c 'chown -R 25000:25000 /steam ; chown -R 25000:25000 /steamcmd ; chown -R 25000:25000 /server-files ; chown -R 25000:25000 /cluster-shared'"
|
||||||
|
user: root
|
||||||
|
image: "opensuse/leap"
|
||||||
|
volumes:
|
||||||
|
- steam-1:/steam:rw
|
||||||
|
- steamcmd-1:/steamcmd:rw
|
||||||
|
- server-files-1:/server-files:rw
|
||||||
|
- cluster-shared:/cluster-shared:rw
|
||||||
|
# asa-server-2:
|
||||||
|
# container_name: asa-server-2
|
||||||
|
# hostname: asa-server-2
|
||||||
|
# entrypoint: "/usr/bin/start_server"
|
||||||
|
# user: gameserver
|
||||||
|
# image: "mschnitzer/asa-linux-server:development"
|
||||||
|
# tty: true
|
||||||
|
# environment:
|
||||||
|
# - ASA_START_PARAMS=ScorchedEarth_WP?listen?Port=7778?RCONPort=27021?RCONEnabled=True -WinLiveMaxPlayers=50 -clusterid=default -ClusterDirOverride="/home/gameserver/cluster-shared"
|
||||||
|
# ports:
|
||||||
|
# # Game port for player connections through the server browser
|
||||||
|
# - 0.0.0.0:7778:7778/udp
|
||||||
|
# # RCON port for remote server administration
|
||||||
|
# - 0.0.0.0:27021:27021/tcp
|
||||||
|
# depends_on:
|
||||||
|
# - set-permissions-2
|
||||||
|
# volumes:
|
||||||
|
# - steam-2:/home/gameserver/Steam:rw
|
||||||
|
# - steamcmd-2:/home/gameserver/steamcmd:rw
|
||||||
|
# - server-files-2:/home/gameserver/server-files:rw
|
||||||
|
# - cluster-shared:/home/gameserver/cluster-shared:rw
|
||||||
|
# - /etc/localtime:/etc/localtime:ro
|
||||||
|
# - ./root/usr/share/asa-ctrl:/usr/share/asa-ctrl:rw
|
||||||
|
# networks:
|
||||||
|
# asa-network:
|
||||||
|
# set-permissions-2:
|
||||||
|
# entrypoint: "/bin/bash -c 'chown -R 25000:25000 /steam ; chown -R 25000:25000 /steamcmd ; chown -R 25000:25000 /server-files ; chown -R 25000:25000 /cluster-shared'"
|
||||||
|
# user: root
|
||||||
|
# image: "opensuse/leap"
|
||||||
|
# volumes:
|
||||||
|
# - steam-2:/steam:rw
|
||||||
|
# - steamcmd-2:/steamcmd:rw
|
||||||
|
# - server-files-2:/server-files:rw
|
||||||
|
# - cluster-shared:/cluster-shared:rw
|
||||||
|
volumes:
|
||||||
|
cluster-shared:
|
||||||
|
steam-1:
|
||||||
|
steamcmd-1:
|
||||||
|
server-files-1:
|
||||||
|
# steam-2:
|
||||||
|
# steamcmd-2:
|
||||||
|
# server-files-2:
|
||||||
|
networks:
|
||||||
|
asa-network:
|
||||||
|
attachable: true
|
||||||
|
driver: bridge
|
||||||
|
driver_opts:
|
||||||
|
com.docker.network.bridge.name: 'asanet'
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
version: "3.3"
|
||||||
|
services:
|
||||||
|
asa-server-1:
|
||||||
|
container_name: asa-server-1
|
||||||
|
hostname: asa-server-1
|
||||||
|
entrypoint: "/usr/bin/start_server"
|
||||||
|
user: gameserver
|
||||||
|
image: "mschnitzer/asa-linux-server:latest"
|
||||||
|
tty: true
|
||||||
|
environment:
|
||||||
|
- ASA_START_PARAMS=TheIsland_WP?listen?Port=7777?RCONPort=27020?RCONEnabled=True -WinLiveMaxPlayers=50 -clusterid=default -ClusterDirOverride="/home/gameserver/cluster-shared"
|
||||||
|
- ENABLE_DEBUG=0
|
||||||
|
ports:
|
||||||
|
# Game port for player connections through the server browser
|
||||||
|
- 0.0.0.0:7777:7777/udp
|
||||||
|
# RCON port for remote server administration
|
||||||
|
- 0.0.0.0:27020:27020/tcp
|
||||||
|
depends_on:
|
||||||
|
- set-permissions-1
|
||||||
|
volumes:
|
||||||
|
- steam-1:/home/gameserver/Steam:rw
|
||||||
|
- steamcmd-1:/home/gameserver/steamcmd:rw
|
||||||
|
- server-files-1:/home/gameserver/server-files:rw
|
||||||
|
- cluster-shared:/home/gameserver/cluster-shared:rw
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
networks:
|
||||||
|
asa-network:
|
||||||
|
set-permissions-1:
|
||||||
|
entrypoint: "/bin/bash -c 'chown -R 25000:25000 /steam ; chown -R 25000:25000 /steamcmd ; chown -R 25000:25000 /server-files ; chown -R 25000:25000 /cluster-shared'"
|
||||||
|
user: root
|
||||||
|
image: "opensuse/leap"
|
||||||
|
volumes:
|
||||||
|
- steam-1:/steam:rw
|
||||||
|
- steamcmd-1:/steamcmd:rw
|
||||||
|
- server-files-1:/server-files:rw
|
||||||
|
- cluster-shared:/cluster-shared:rw
|
||||||
|
# asa-server-2:
|
||||||
|
# container_name: asa-server-2
|
||||||
|
# hostname: asa-server-2
|
||||||
|
# entrypoint: "/usr/bin/start_server"
|
||||||
|
# user: gameserver
|
||||||
|
# image: "mschnitzer/asa-linux-server:latest"
|
||||||
|
# tty: true
|
||||||
|
# environment:
|
||||||
|
# - ASA_START_PARAMS=ScorchedEarth_WP?listen?Port=7778?RCONPort=27021?RCONEnabled=True -WinLiveMaxPlayers=50 -clusterid=default -ClusterDirOverride="/home/gameserver/cluster-shared"
|
||||||
|
# ports:
|
||||||
|
# # Game port for player connections through the server browser
|
||||||
|
# - 0.0.0.0:7778:7778/udp
|
||||||
|
# # RCON port for remote server administration
|
||||||
|
# - 0.0.0.0:27021:27021/tcp
|
||||||
|
# depends_on:
|
||||||
|
# - set-permissions-2
|
||||||
|
# volumes:
|
||||||
|
# - steam-2:/home/gameserver/Steam:rw
|
||||||
|
# - steamcmd-2:/home/gameserver/steamcmd:rw
|
||||||
|
# - server-files-2:/home/gameserver/server-files:rw
|
||||||
|
# - cluster-shared:/home/gameserver/cluster-shared:rw
|
||||||
|
# - /etc/localtime:/etc/localtime:ro
|
||||||
|
# networks:
|
||||||
|
# asa-network:
|
||||||
|
# set-permissions-2:
|
||||||
|
# entrypoint: "/bin/bash -c 'chown -R 25000:25000 /steam ; chown -R 25000:25000 /steamcmd ; chown -R 25000:25000 /server-files ; chown -R 25000:25000 /cluster-shared'"
|
||||||
|
# user: root
|
||||||
|
# image: "opensuse/leap"
|
||||||
|
# volumes:
|
||||||
|
# - steam-2:/steam:rw
|
||||||
|
# - steamcmd-2:/steamcmd:rw
|
||||||
|
# - server-files-2:/server-files:rw
|
||||||
|
# - cluster-shared:/cluster-shared:rw
|
||||||
|
volumes:
|
||||||
|
cluster-shared:
|
||||||
|
steam-1:
|
||||||
|
steamcmd-1:
|
||||||
|
server-files-1:
|
||||||
|
# steam-2:
|
||||||
|
# steamcmd-2:
|
||||||
|
# server-files-2:
|
||||||
|
networks:
|
||||||
|
asa-network:
|
||||||
|
attachable: true
|
||||||
|
driver: bridge
|
||||||
|
driver_opts:
|
||||||
|
com.docker.network.bridge.name: 'asanet'
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
#!/usr/bin/ruby.ruby3.4
|
||||||
|
require 'json'
|
||||||
|
|
||||||
|
db_path = '/home/gameserver/server-files/mods.json'
|
||||||
|
|
||||||
|
unless File.exist?(db_path)
|
||||||
|
print ""
|
||||||
|
exit! 0
|
||||||
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
mods = JSON.parse(File.read(db_path))
|
||||||
|
args = "-mods="
|
||||||
|
counter = 0
|
||||||
|
|
||||||
|
mods.each do |mod|
|
||||||
|
if mod['enabled']
|
||||||
|
args += ',' if counter > 0
|
||||||
|
args += mod['mod_id'].to_s
|
||||||
|
|
||||||
|
counter += 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if counter > 0
|
||||||
|
print args
|
||||||
|
end
|
||||||
|
rescue JSON::ParserError
|
||||||
|
File.write('/tmp/mod-read-error', 'mods.json is corrupted')
|
||||||
|
print ""
|
||||||
|
rescue => err
|
||||||
|
File.write('/tmp/mod-read-error', err.to_s)
|
||||||
|
print ""
|
||||||
|
end
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
if [ "$ENABLE_DEBUG" = "1" ]; then
|
||||||
|
echo "Entering debug mode..."
|
||||||
|
sleep 999999999999
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# download steamcmd if necessary
|
||||||
|
if [ ! -d "/home/gameserver/steamcmd/linux32" ]; then
|
||||||
|
cd /home/gameserver/steamcmd
|
||||||
|
wget https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz
|
||||||
|
tar xfvz steamcmd_linux.tar.gz
|
||||||
|
fi
|
||||||
|
|
||||||
|
# download/update server files
|
||||||
|
cd /home/gameserver/steamcmd
|
||||||
|
./steamcmd.sh +force_install_dir /home/gameserver/server-files +login anonymous +app_update 2430930 validate +quit
|
||||||
|
|
||||||
|
PROTON_VERSION="10-17"
|
||||||
|
PROTON_DIR_NAME="GE-Proton$PROTON_VERSION"
|
||||||
|
PROTON_ARCHIVE_NAME="$PROTON_DIR_NAME.tar.gz"
|
||||||
|
STEAM_COMPAT_DATA=/home/gameserver/server-files/steamapps/compatdata
|
||||||
|
STEAM_COMPAT_DIR=/home/gameserver/Steam/compatibilitytools.d
|
||||||
|
ASA_COMPAT_DATA=$STEAM_COMPAT_DATA/2430930
|
||||||
|
ASA_BINARY_DIR="/home/gameserver/server-files/ShooterGame/Binaries/Win64"
|
||||||
|
START_PARAMS_FILE="/home/gameserver/server-files/start-parameters"
|
||||||
|
MODS="$(/usr/bin/cli-asa-mods)"
|
||||||
|
ASA_START_PARAMS="$ASA_START_PARAMS $MODS"
|
||||||
|
ASA_BINARY_NAME="ArkAscendedServer.exe"
|
||||||
|
ASA_PLUGIN_BINARY_NAME="AsaApiLoader.exe"
|
||||||
|
ASA_PLUGIN_LOADER_ARCHIVE_NAME=$(basename $ASA_BINARY_DIR/AsaApi_*.zip)
|
||||||
|
ASA_PLUGIN_LOADER_ARCHIVE_PATH="$ASA_BINARY_DIR/$ASA_PLUGIN_LOADER_ARCHIVE_NAME"
|
||||||
|
ASA_PLUGIN_BINARY_PATH="$ASA_BINARY_DIR/$ASA_PLUGIN_BINARY_NAME"
|
||||||
|
LAUNCH_BINARY_NAME="$ASA_BINARY_NAME"
|
||||||
|
|
||||||
|
# install proton if necessary
|
||||||
|
if [ ! -d "$STEAM_COMPAT_DIR/$PROTON_DIR_NAME" ]; then
|
||||||
|
mkdir -p $STEAM_COMPAT_DIR
|
||||||
|
echo "Downloading Proton version $PROTON_VERSION... This might take a while"
|
||||||
|
wget -P /tmp https://github.com/GloriousEggroll/proton-ge-custom/releases/download/GE-Proton$PROTON_VERSION/GE-Proton$PROTON_VERSION.tar.gz
|
||||||
|
EXIT_CODE=$?
|
||||||
|
|
||||||
|
if [ $EXIT_CODE -ne 0 ]; then
|
||||||
|
echo "Error: Error while downloading Proton ($EXIT_CODE)"
|
||||||
|
exit 200
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Download finished, comparing checksums..."
|
||||||
|
sha512sum -c /usr/share/proton/GE-Proton$PROTON_VERSION.sha512sum
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "Error: Proton checksum mismatch!"
|
||||||
|
exit 201
|
||||||
|
fi
|
||||||
|
|
||||||
|
tar -xf /tmp/$PROTON_ARCHIVE_NAME -C $STEAM_COMPAT_DIR
|
||||||
|
rm /tmp/$PROTON_ARCHIVE_NAME
|
||||||
|
fi
|
||||||
|
|
||||||
|
# install proton compat game data
|
||||||
|
if [ ! -d "$ASA_COMPAT_DATA" ]; then
|
||||||
|
mkdir -p $STEAM_COMPAT_DATA
|
||||||
|
cp -r $STEAM_COMPAT_DIR/$PROTON_DIR_NAME/files/share/default_pfx $ASA_COMPAT_DATA
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Starting the ARK: Survival Ascended dedicated server..."
|
||||||
|
echo "Start parameters: $ASA_START_PARAMS"
|
||||||
|
|
||||||
|
export XDG_RUNTIME_DIR=/run/user/$(id -u)
|
||||||
|
export STEAM_COMPAT_CLIENT_INSTALL_PATH=/home/gameserver/Steam
|
||||||
|
export STEAM_COMPAT_DATA_PATH=$ASA_COMPAT_DATA
|
||||||
|
|
||||||
|
cd "$ASA_BINARY_DIR"
|
||||||
|
|
||||||
|
# unzip the asa plugin api archive if it exists. delete it afterwards
|
||||||
|
if [ -f "$ASA_PLUGIN_LOADER_ARCHIVE_PATH" ]; then
|
||||||
|
unzip -o $ASA_PLUGIN_LOADER_ARCHIVE_NAME
|
||||||
|
rm $ASA_PLUGIN_LOADER_ARCHIVE_NAME
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$ASA_PLUGIN_BINARY_PATH" ]; then
|
||||||
|
echo "Detected ASA Server API loader. Launching server through $ASA_PLUGIN_BINARY_NAME"
|
||||||
|
LAUNCH_BINARY_NAME="$ASA_PLUGIN_BINARY_NAME"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove steamclient64.dll to prevent server from crashing.
|
||||||
|
# File is not needed and was probably accidentally committed to Steam.
|
||||||
|
# See: https://github.com/mschnitzer/ark-survival-ascended-linux-container-image/issues/123
|
||||||
|
rm -f /home/gameserver/server-files/ShooterGame/Binaries/Win64/steamclient64.dll
|
||||||
|
|
||||||
|
$STEAM_COMPAT_DIR/$PROTON_DIR_NAME/proton run $LAUNCH_BINARY_NAME $ASA_START_PARAMS
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
source 'https://rubygems.org'
|
||||||
|
|
||||||
|
gem 'slop', '= 4.10.1'
|
||||||
|
gem 'iniparse', '= 1.5.0'
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
GEM
|
||||||
|
remote: https://rubygems.org/
|
||||||
|
specs:
|
||||||
|
iniparse (1.5.0)
|
||||||
|
slop (4.10.1)
|
||||||
|
|
||||||
|
PLATFORMS
|
||||||
|
x86_64-linux-gnu
|
||||||
|
|
||||||
|
DEPENDENCIES
|
||||||
|
iniparse (= 1.5.0)
|
||||||
|
slop (= 4.10.1)
|
||||||
|
|
||||||
|
BUNDLED WITH
|
||||||
|
2.5.0.dev
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
module AsaCtrl
|
||||||
|
module Cli
|
||||||
|
class CliInterface
|
||||||
|
def initialize(opts)
|
||||||
|
@opts = opts
|
||||||
|
|
||||||
|
print_help! if opts[:help]
|
||||||
|
end
|
||||||
|
|
||||||
|
def print_help!
|
||||||
|
raise "Help not implemented!"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
module AsaCtrl
|
||||||
|
module Cli
|
||||||
|
class ModsInterface < CliInterface
|
||||||
|
def initialize(opts)
|
||||||
|
super(opts)
|
||||||
|
|
||||||
|
execute!
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute!
|
||||||
|
if @opts[:enable]
|
||||||
|
enable_mod!
|
||||||
|
end
|
||||||
|
|
||||||
|
exit! AsaCtrl::ExitCodes::OK
|
||||||
|
end
|
||||||
|
|
||||||
|
def enable_mod!
|
||||||
|
mod_id = @opts[:enable]
|
||||||
|
AsaCtrl::Mods::Database.get_instance.enable_mod!(mod_id)
|
||||||
|
|
||||||
|
puts "Enabled mod id '#{mod_id}' successfully. The server will download the mod upon startup."
|
||||||
|
rescue AsaCtrl::Errors::ModAlreadyEnabledError
|
||||||
|
AsaCtrl::Cli.exit_with_error!("This mod is already enabled! Use 'asa-ctrl mods --list' to see what mods are currently enabled.",
|
||||||
|
AsaCtrl::ExitCodes::MOD_ALREADY_ENABLED)
|
||||||
|
end
|
||||||
|
|
||||||
|
def print_help!
|
||||||
|
puts "Usage: asa-ctrl mods [--install] (--dry-run)"
|
||||||
|
exit! AsaCtrl::ExitCodes::OK
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
module AsaCtrl
|
||||||
|
module Cli
|
||||||
|
class RconInterface < CliInterface
|
||||||
|
def initialize(opts)
|
||||||
|
super(opts)
|
||||||
|
|
||||||
|
execute!
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute!
|
||||||
|
if @opts[:exec]
|
||||||
|
run_command!
|
||||||
|
end
|
||||||
|
|
||||||
|
exit! AsaCtrl::ExitCodes::OK
|
||||||
|
end
|
||||||
|
|
||||||
|
def run_command!
|
||||||
|
rcon_command = @opts[:exec]
|
||||||
|
response = AsaCtrl::Rcon.exec_command!('127.0.0.1', AsaCtrl::Rcon.identify_port, rcon_command, AsaCtrl::Rcon.identify_password)
|
||||||
|
|
||||||
|
if response[:id] == AsaCtrl::Rcon::PacketTypes::RESPONSE_VALUE
|
||||||
|
puts response[:body]
|
||||||
|
else
|
||||||
|
AsaCtrl::Cli.exit_with_error!("Rcon command execution failed: #{response}",
|
||||||
|
AsaCtrl::ExitCodes::RCON_COMMAND_EXECUTION_FAILED)
|
||||||
|
end
|
||||||
|
rescue AsaCtrl::Errors::RconPasswordNotFoundError
|
||||||
|
AsaCtrl::Cli.exit_with_error!("Could not read RCON password. Make sure it is properly configured, either as start parameter ?ServerAdminPassword=mypass or " \
|
||||||
|
"in GameUserSettings.ini in the [ServerSettings] section as ServerAdminPassword=mypass", AsaCtrl::ExitCodes::RCON_PASSWORD_NOT_FOUND)
|
||||||
|
rescue AsaCtrl::Errors::RconAuthenticationError
|
||||||
|
AsaCtrl::Cli.exit_with_error!("Could not execute this RCON command. Authentication failed (wrong server password).",
|
||||||
|
AsaCtrl::ExitCodes::RCON_PASSWORD_WRONG)
|
||||||
|
end
|
||||||
|
|
||||||
|
def print_help!
|
||||||
|
puts "Usage: asa-ctrl rcon [--exec]"
|
||||||
|
exit! AsaCtrl::ExitCodes::OK
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
module AsaCtrl
|
||||||
|
module Cli
|
||||||
|
HELP_ARGUMENT = '--help'
|
||||||
|
HELP_DESCRIPTION = 'Prints a help message'
|
||||||
|
|
||||||
|
def self.passed_command(args)
|
||||||
|
if ARGV.size == 0
|
||||||
|
[]
|
||||||
|
else
|
||||||
|
[ARGV[0]]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.print_usage
|
||||||
|
puts "Usage: asa-ctrl [rcon] (--help)"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exit_with_error!(message, code)
|
||||||
|
$stderr.puts "Error: #{message}"
|
||||||
|
exit! code
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
module AsaCtrl
|
||||||
|
module Errors
|
||||||
|
class BaseError < StandardError; end
|
||||||
|
end
|
||||||
|
end
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
require_relative './base_error.rb'
|
||||||
|
require_relative './mod_already_enabled_error.rb'
|
||||||
|
require_relative './rcon_authentication_error.rb'
|
||||||
|
require_relative './rcon_password_not_found_error.rb'
|
||||||
|
require_relative './rcon_port_not_found_error.rb'
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
module AsaCtrl
|
||||||
|
module Errors
|
||||||
|
class ModAlreadyEnabledError < BaseError; end
|
||||||
|
end
|
||||||
|
end
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
module AsaCtrl
|
||||||
|
module Errors
|
||||||
|
class RconAuthenticationError < BaseError; end
|
||||||
|
end
|
||||||
|
end
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
module AsaCtrl
|
||||||
|
module Errors
|
||||||
|
class RconPasswordNotFoundError < BaseError; end
|
||||||
|
end
|
||||||
|
end
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
module AsaCtrl
|
||||||
|
module Errors
|
||||||
|
class RconPortNotFoundError < BaseError; end
|
||||||
|
end
|
||||||
|
end
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
module AsaCtrl
|
||||||
|
module ExitCodes
|
||||||
|
OK = 0
|
||||||
|
CORRUPTED_MODS_DATABASE = 1
|
||||||
|
MOD_ALREADY_ENABLED = 2
|
||||||
|
RCON_PASSWORD_NOT_FOUND = 3
|
||||||
|
RCON_PASSWORD_WRONG = 4
|
||||||
|
RCON_COMMAND_EXECUTION_FAILED = 5
|
||||||
|
end
|
||||||
|
end
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
require_relative './start_params_helper.rb'
|
||||||
|
require_relative './ini_config_helper.rb'
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
module AsaCtrl
|
||||||
|
module IniConfigHelper
|
||||||
|
def self.game_user_settings_ini
|
||||||
|
self.parse('/home/gameserver/server-files/ShooterGame/Saved/Config/WindowsServer/GameUserSettings.ini')
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.game_ini
|
||||||
|
self.parse('/home/gameserver/server-files/ShooterGame/Saved/Config/WindowsServer/Game.ini')
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.parse(path)
|
||||||
|
return unless File.exist?(path)
|
||||||
|
|
||||||
|
IniParse.parse(File.read(path))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
module AsaCtrl
|
||||||
|
module StartParamsHelper
|
||||||
|
def self.get_value(start_params, key)
|
||||||
|
return unless start_params
|
||||||
|
|
||||||
|
value = ''
|
||||||
|
offset = start_params.index("#{key}=")
|
||||||
|
|
||||||
|
return unless offset
|
||||||
|
|
||||||
|
offset += "#{key}=".length
|
||||||
|
|
||||||
|
start_params[offset..-1].each_char do |char|
|
||||||
|
break if char == ' ' || char == '?'
|
||||||
|
|
||||||
|
value += char
|
||||||
|
end
|
||||||
|
|
||||||
|
value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Executable
+36
@@ -0,0 +1,36 @@
|
|||||||
|
#!/usr/bin/ruby.ruby3.4
|
||||||
|
require 'json'
|
||||||
|
require 'slop'
|
||||||
|
require 'iniparse'
|
||||||
|
require 'socket'
|
||||||
|
|
||||||
|
if ENV['DEV'] == '1'
|
||||||
|
require 'byebug'
|
||||||
|
end
|
||||||
|
|
||||||
|
require_relative './exit_codes.rb'
|
||||||
|
require_relative './errors/errors.rb'
|
||||||
|
require_relative './helpers/helpers.rb'
|
||||||
|
require_relative './mods/database.rb'
|
||||||
|
require_relative './rcon/rcon.rb'
|
||||||
|
require_relative './cli/utils.rb'
|
||||||
|
require_relative './cli/interfaces/cli_interface.rb'
|
||||||
|
require_relative './cli/interfaces/mods_interface.rb'
|
||||||
|
require_relative './cli/interfaces/rcon_interface.rb'
|
||||||
|
|
||||||
|
main_args = Slop.parse(AsaCtrl::Cli.passed_command(ARGV)) do |args|
|
||||||
|
args.on 'rcon', 'Interface for RCON command execution' do
|
||||||
|
opts = Slop.parse(ARGV[1..-1]) do |opt|
|
||||||
|
opt.string '--exec', 'An RCON command to execute'
|
||||||
|
opt.bool AsaCtrl::Cli::HELP_ARGUMENT, AsaCtrl::Cli::HELP_DESCRIPTION
|
||||||
|
end
|
||||||
|
|
||||||
|
AsaCtrl::Cli::RconInterface.new(opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
args.on AsaCtrl::Cli::HELP_ARGUMENT, AsaCtrl::Cli::HELP_DESCRIPTION do
|
||||||
|
# handled once slop exits
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
AsaCtrl::Cli.print_usage
|
||||||
+66
@@ -0,0 +1,66 @@
|
|||||||
|
module AsaCtrl
|
||||||
|
module Mods
|
||||||
|
MOD_DATABASE_PATH = '/home/gameserver/server-files/mods.json'
|
||||||
|
|
||||||
|
class Database
|
||||||
|
@@singleton_reference = nil
|
||||||
|
|
||||||
|
def initialize(database_path)
|
||||||
|
@database_path = database_path
|
||||||
|
|
||||||
|
ensure_database_presence!
|
||||||
|
load_database
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.get_instance
|
||||||
|
return @@singleton_reference if @@singleton_reference
|
||||||
|
@@singleton_reference = Database.new(MOD_DATABASE_PATH)
|
||||||
|
end
|
||||||
|
|
||||||
|
def enable_mod!(mod_id)
|
||||||
|
@database.each do |record|
|
||||||
|
if record['mod_id'].to_i == mod_id.to_i
|
||||||
|
raise AsaCtrl::Errors::ModAlreadyEnabledError if record['enabled']
|
||||||
|
|
||||||
|
record['enabled'] = true
|
||||||
|
write_database!
|
||||||
|
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
add_new_record!(mod_id, 'unknown', true, false)
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_new_record!(mod_id, name, enabled, scanned)
|
||||||
|
@database << {
|
||||||
|
mod_id: mod_id.to_i,
|
||||||
|
name: name,
|
||||||
|
enabled: enabled,
|
||||||
|
scanned: scanned
|
||||||
|
}
|
||||||
|
|
||||||
|
write_database!
|
||||||
|
end
|
||||||
|
|
||||||
|
def write_database!
|
||||||
|
File.write(@database_path, JSON.pretty_generate(@database))
|
||||||
|
end
|
||||||
|
|
||||||
|
def ensure_database_presence!
|
||||||
|
return if File.exist?(@database_path)
|
||||||
|
|
||||||
|
@database = []
|
||||||
|
write_database!
|
||||||
|
end
|
||||||
|
|
||||||
|
def load_database
|
||||||
|
@database = JSON.parse(File.read(@database_path))
|
||||||
|
rescue JSON::ParserError
|
||||||
|
# we do not want to delete the file for the user, as they might want to save its content first
|
||||||
|
AsaCtrl::Cli.exit_with_error!("mods.json file is corrupted and cannot be parsed, please delete this file " \
|
||||||
|
"manually. It can be found in the server files root directory.", AsaCtrl::ExitCodes::CORRUPTED_MODS_DATABASE)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
+69
@@ -0,0 +1,69 @@
|
|||||||
|
module AsaCtrl
|
||||||
|
module Rcon
|
||||||
|
module PacketTypes
|
||||||
|
RESPONSE_VALUE = 0
|
||||||
|
EXEC_COMMAND = 2
|
||||||
|
AUTH_RESPONSE = 2
|
||||||
|
AUTH = 3
|
||||||
|
end
|
||||||
|
|
||||||
|
Packet = Struct.new(:size, :id, :type, :body)
|
||||||
|
|
||||||
|
def self.exec_command!(server_ip, rcon_port, rcon_command, password)
|
||||||
|
socket = TCPSocket.new(server_ip, rcon_port)
|
||||||
|
raise AsaCtrl::Errors::RconAuthenticationError unless self.authenticate!(socket, password)
|
||||||
|
|
||||||
|
self.send_packet!(socket, rcon_command, PacketTypes::EXEC_COMMAND)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.authenticate!(socket, password)
|
||||||
|
response = self.send_packet!(socket, password, PacketTypes::AUTH)
|
||||||
|
response[:id] != -1
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.send_packet!(socket, data, packet_id)
|
||||||
|
packet = Packet.new(10+data.bytesize, 0, packet_id, data)
|
||||||
|
|
||||||
|
self.send_to(packet, socket)
|
||||||
|
self.recv_from(socket)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.send_to(packet, socket)
|
||||||
|
szb = [packet[:size]].pack 'l<'
|
||||||
|
idb = [packet[:id]].pack 'l<'
|
||||||
|
type_b = [packet[:type]].pack 'l<'
|
||||||
|
body_b = [packet[:body]].pack 'Z*'
|
||||||
|
data = szb + idb + type_b + body_b + "\0"
|
||||||
|
|
||||||
|
socket.sendmsg(data)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.recv_from(socket)
|
||||||
|
msg_ary = socket.recvmsg
|
||||||
|
msg = msg_ary[0]
|
||||||
|
ary = msg.unpack('l<l<l<Z*')
|
||||||
|
|
||||||
|
Packet.new(ary[0], ary[1], ary[2], ary[3])
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.identify_password
|
||||||
|
password = AsaCtrl::StartParamsHelper.get_value(ENV['ASA_START_PARAMS'], 'ServerAdminPassword')
|
||||||
|
return password if password
|
||||||
|
|
||||||
|
config = AsaCtrl::IniConfigHelper.game_user_settings_ini
|
||||||
|
return config['ServerSettings']['ServerAdminPassword'] if config['ServerSettings'] && config['ServerSettings']['ServerAdminPassword']
|
||||||
|
|
||||||
|
raise AsaCtrl::Errors::RconPasswordNotFoundError
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.identify_port
|
||||||
|
port = AsaCtrl::StartParamsHelper.get_value(ENV['ASA_START_PARAMS'], 'RCONPort')
|
||||||
|
return port.to_i if port
|
||||||
|
|
||||||
|
config = AsaCtrl::IniConfigHelper.game_user_settings_ini
|
||||||
|
return config['ServerSettings']['RCONPort'].to_i if config['ServerSettings'] && config['ServerSettings']['RCONPort']
|
||||||
|
|
||||||
|
raise AsaCtrl::Errors::RconPortNotFoundError
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
d21bd48479ab35213a7bf5b7eb87d0f156da16891cdc6bed3665e268811304c20cc9834ff901b9d4e31abc6d10bf6b8066276d32f7c487607270a3a9f975ae2c /tmp/GE-Proton10-17.tar.gz
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
name: ark-survival-ascended
|
||||||
|
|
||||||
|
services:
|
||||||
|
server:
|
||||||
|
image: mschnitzer/asa-linux-server@sha256:6a62f7c6eb77ba4b4b79ef6c2981a0bd9fab287e744d9797e66efc762ebb811e
|
||||||
|
container_name: ark-survival-ascended
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Stockholm
|
||||||
|
PUID: "1000"
|
||||||
|
PGID: "1000"
|
||||||
|
WEBUI_PORT: "8080"
|
||||||
|
|
||||||
|
ports:
|
||||||
|
- target: 8080
|
||||||
|
published: "8080"
|
||||||
|
protocol: tcp
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: /DATA/AppData/$AppID/config
|
||||||
|
target: /config
|
||||||
|
|
||||||
|
# Secure-by-default baseline. Relax only if appen kräver det.
|
||||||
|
security_opt:
|
||||||
|
- no-new-privileges:true
|
||||||
|
cap_drop:
|
||||||
|
- ALL
|
||||||
|
|
||||||
|
x-casaos:
|
||||||
|
envs:
|
||||||
|
- container: TZ
|
||||||
|
description:
|
||||||
|
en_US: Timezone, for example Europe/Stockholm
|
||||||
|
- container: PUID
|
||||||
|
description:
|
||||||
|
en_US: User ID for filesystem permissions
|
||||||
|
- container: PGID
|
||||||
|
description:
|
||||||
|
en_US: Group ID for filesystem permissions
|
||||||
|
ports:
|
||||||
|
- container: "8080"
|
||||||
|
description:
|
||||||
|
en_US: Web UI port
|
||||||
|
volumes:
|
||||||
|
- container: /config
|
||||||
|
description:
|
||||||
|
en_US: Application configuration directory
|
||||||
|
|
||||||
|
x-casaos:
|
||||||
|
architectures:
|
||||||
|
- amd64
|
||||||
|
- arm64
|
||||||
|
main: server
|
||||||
|
category: phirna
|
||||||
|
author: Joachim Friberg
|
||||||
|
developer: Joachim Friberg
|
||||||
|
icon: https://cdn.simpleicons.org/docker
|
||||||
|
tagline:
|
||||||
|
en_US: Replace with a short one-line value proposition
|
||||||
|
description:
|
||||||
|
en_US: Replace with a clear description of what the app does
|
||||||
|
title:
|
||||||
|
en_US: Sample App
|
||||||
|
index: /
|
||||||
|
port_map: "8080"
|
||||||
|
|
||||||
Submodule Apps/ark-survival-ascended-linux-container-image deleted from 6e0c43e790
Vendored
BIN
Binary file not shown.
Reference in New Issue
Block a user