aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/PRODUCTION.md364
1 files changed, 364 insertions, 0 deletions
diff --git a/docs/PRODUCTION.md b/docs/PRODUCTION.md
new file mode 100644
index 0000000..dfb70e5
--- /dev/null
+++ b/docs/PRODUCTION.md
@@ -0,0 +1,364 @@
+# Production configuration
+
+This document describes the recommended setup for an non-containerized Atlas server.
+
+## System requirements
+
+| Dependency | Version | Notes |
+| --- | --- | --- |
+| go | 1.19+ | |
+| gcc | | other C compilers will work fine |
+| systemd | 250+ | 250 is needed for credentials to work <br/> 240 is needed for data directory stuff |
+| logrotate | 3.18.0+ | older versions may also work |
+| zstd | | optional, for logrotate compression |
+| sqlite3 | 3.37+ | 3.37 is needed for strict tables |
+
+## Installation
+
+1. Install Atlas.
+
+ ```bash
+ # option 1: latest version
+ sudo GOBIN=/usr/local/bin go install -v -trimpath github.com/r2northstar/atlas/cmd/...@main
+ ```
+
+ ```bash
+ # option 2: from local git clone
+ git clone https://github.com/r2northstar/atlas
+ cd atlas
+ sudo GOBIN=/usr/local/bin go install -v -trimpath github.com/r2northstar/atlas/cmd/...
+ ```
+
+ To update it later, use the same `go install` command.
+
+2. Install the website files.
+
+ ```bash
+ sudo git clone https://github.com/R2Northstar/NorthstarTF /usr/share/northstartf
+ ```
+
+ To update it later:
+
+ ```bash
+ sudo git -C /usr/share/northstartf pull
+ ```
+
+3. Download the [IP2Location](https://lite.ip2location.com) DB5 (or higher) database.
+
+ If you update it later while Atlas is running, you will need to run `/usr/bin/systemctl kill --signal=SIGHUP atlas.service`.
+
+4. Set up the Atlas service user and group.
+
+ ```bash
+ # create the user/group
+ sudo useradd --system --shell /usr/sbin/nologin --home-dir /var/lib/atlas atlas
+ ```
+
+ ```bash
+ # give another user direct read-only log and database access
+ sudo usermod -aG atlas youruser
+ ```
+
+5. Configure Atlas.
+
+ ```bash
+ sudo mkdir /etc/atlas
+ sudo nano /etc/atlas/config
+ ```
+
+ Example configuration (see [pkg/atlas.Config](../pkg/atlas/config.go) for config docs):
+
+ ```properties
+ # listen config
+ ATLAS_ADDR=
+ ATLAS_ADDR_HTTPS=:443
+ ATLAS_CLOUDFLARE=true
+ ATLAS_HOST=northstar.tf
+ ATLAS_SERVER_CERTS=@northstartf
+
+ # don't need debug or lower log levels
+ ATLAS_LOG_LEVEL=info
+
+ # log pretty error+ logs to stdout/journald
+ ATLAS_LOG_STDOUT=true
+ ATLAS_LOG_STDOUT_PRETTY=true
+ ATLAS_LOG_STDOUT_LEVEL=error
+
+ # log info+ logs to the log file
+ ATLAS_LOG_FILE=/var/log/atlas/atlas.log
+ ATLAS_LOG_FILE_LEVEL=info
+ ATLAS_LOG_FILE_CHMOD=0640
+
+ # original master server api config
+ ATLAS_API0_MAX_SERVERS=1000
+ ATLAS_API0_MAX_SERVERS_PER_IP=25
+ ATLAS_API0_TOKEN_EXPIRY_TIME=24h
+ ATLAS_API0_ALLOW_GAME_SERVER_IPV6=false
+ ATLAS_API0_MINIMUM_LAUNCHER_VERSION=1.9.7
+ ATLAS_API0_REGION_MAP=default
+ ATLAS_API0_SERVERLIST_EXPERIMENTAL_DETERMINISTIC_SERVER_ID_SECRET=@api0_server_id_secret
+ ATLAS_API0_SERVERLIST_VERIFY_TIME=10s
+ ATLAS_API0_SERVERLIST_DEAD_TIME=30s
+ ATLAS_API0_SERVERLIST_GHOST_TIME=2m
+ ATLAS_API0_STORAGE_ACCOUNTS=sqlite3:/var/lib/atlas/accounts.db
+ ATLAS_API0_STORAGE_PDATA=sqlite3:/var/lib/atlas/pdata.db
+ ATLAS_API0_MAINMENUPROMOS=file:/etc/atlas/mainmenupromos.json
+
+ # origin (the account MUST have app-based two-factor authentication set up)
+ ATLAS_ORIGIN_EMAIL=email@example.com
+ ATLAS_ORIGIN_PASSWORD=@origin_password
+ ATLAS_ORIGIN_TOTP=@origin_totp
+ ATLAS_ORIGIN_HAR_GZIP=true
+ ATLAS_ORIGIN_HAR_SUCCESS=/var/log/atlas/har
+ ATLAS_ORIGIN_HAR_ERROR=/var/log/atlas/har
+ ATLAS_ORIGIN_PERSIST=/var/lib/atlas/origin.json
+
+ # metrics
+ ATLAS_METRICS_SECRET=@metrics_secret
+
+ # web
+ ATLAS_WEB=/usr/share/northstartf/dist
+
+ # ip2location
+ ATLAS_IP2LOCATION=/usr/share/ip2location-lite/IP2LOCATION-LITE-DB11.IPV6.BIN
+ ```
+
+ Note: The `@` values in the config are references to systemd credentials, which will be described later.
+
+ ```bash
+ sudo nano /etc/atlas/mainmenupromos.json
+ ```
+
+ ```json
+ {
+ "newInfo": {
+ "Title1": "%$rui\/bullet_point%`2This text is yellow`0 and this is white!",
+ "Title2": "%$rui\/bullet_point%Blah blah blah.",
+ "Title3": "%$rui\/bullet_point%Another `2bullet point`0!"
+ },
+ "largeButton": {
+ "Title": "",
+ "Text": "",
+ "Url": "",
+ "ImageIndex": 0
+ },
+ "smallButton1": {
+ "Title": "",
+ "Url": "",
+ "ImageIndex": 0
+ },
+ "smallButton2": {
+ "Title": "",
+ "Url": "",
+ "ImageIndex": 0
+ }
+ }
+ ```
+
+6. Create the systemd unit:
+
+ ```bash
+ sudo nano /etc/systemd/system/atlas.service
+ ```
+
+ ```ini
+ [Unit]
+ Description=Atlas
+ After=network.target
+
+ [Service]
+ Type=notify
+
+ User=atlas
+ Group=atlas
+ ExecStart=/usr/local/bin/atlas /etc/atlas/config
+
+ ConfigurationDirectory=atlas
+ LogsDirectory=atlas
+ StateDirectory=atlas
+ StateDirectoryMode=0750
+
+ AmbientCapabilities=CAP_NET_BIND_SERVICE
+
+ ProtectClock=yes
+ ProtectKernelTunables=yes
+ ProtectKernelModules=yes
+ ProtectKernelLogs=yes
+ ProtectControlGroups=yes
+ ProtectHome=tmpfs
+ ProtectSystem=strict
+ PrivateTmp=yes
+ PrivateDevices=yes
+ PrivateMounts=yes
+
+ LimitNOFILE=32000
+ LimitNPROC=32000
+
+ [Install]
+ WantedBy=multi-user.target
+ ```
+
+7. Set up systemd credentials (doing it this way prevents unprivileged users from reading secrets):
+
+ ```bash
+ sudo mkdir /etc/systemd/system/atlas.service.d
+ echo "[Service]" | tee /etc/systemd/system/atlas.service.d/credentials.conf
+ ```
+
+ For each credential (in the example config: `northstartf.key`, `northstartf.crt`, `api0_server_id_secret`, `metrics_secret`, `origin_password`, `origin_totp`),
+
+ ```bash
+ sudo systemd-creds --pretty encrypt --name credential_name - - | tee -a /etc/systemd/system/atlas.service.d/credentials.conf
+ # paste the data, then press ctrl+d
+ ```
+
+ Note: If you make a mistake or need to change the credentials, you'll need to remove the corresponding lines from `credentials.conf`.
+
+8. Set up logrotate (optional):
+
+ ```bash
+ sudo nano /etc/logrotate.d/atlas
+ ```
+
+ ```
+ /var/log/atlas/atlas.log {
+ daily
+ missingok
+ rotate 900
+ dateext
+ compress
+ compresscmd /usr/bin/zstd
+ compressext .zst
+ compressoptions --long
+ uncompresscmd /usr/bin/unzstd
+ delaycompress
+ postrotate
+ /usr/bin/systemctl kill --signal=SIGHUP atlas.service
+ endscript
+ }
+ ```
+
+ Note: The `postrotate` script is required to tell atlas to re-open log files.
+
+ Note: `delaycompress` is needed to prevent the re-open from being racy.
+
+ ```bash
+ sudo systemctl restart logrotate
+ ```
+
+9. Import data from the old [NorthstarMasterServer](https://github.com/R2Northstar/NorthstarMasterServer) database (optional):
+
+ ```bash
+ sudo mkdir /var/lib/atlas
+ sudo atlas-import --progress /path/to/old/playerdata.db /var/lib/atlas/accounts.db /var/lib/atlas/pdata.db
+ ```
+
+10. Start atlas:
+
+ ```bash
+ sudo systemctl daemon-reload
+ sudo systemctl enable --now atlas.service
+ ```
+
+## Maintenance
+
+ - **Get service status**
+
+ ```bash
+ sudo systemctl status atlas
+ ```
+
+ - **Restart**
+
+ ```bash
+ sudo systemctl restart atlas
+ ```
+
+ - **Reload files** (logs, ip2location db, etc)
+
+ ```bash
+ sudo systemctl kill --signal=SIGHUP atlas
+ ```
+
+ - **Backup databases**
+
+ ```bash
+ sudo -g atlas sqlite3 /var/lib/atlas/accounts.db 'VACUUM INTO "/path/to/backup/accounts.db"'
+ sudo -g atlas sqlite3 /var/lib/atlas/pdata.db 'VACUUM INTO "/path/to/backup/pdata.db"'
+ ```
+
+ This safely creates a consistent backup of a running Atlas instance.
+
+ - **View error logs**
+
+ ```bash
+ sudo journalctl -u atlas
+ ```
+
+ - **View systemd credentials**
+
+ ```bash
+ sudo CREDENTIALS_DIRECTORY=/run/credentials/atlas.service systemd-creds list
+ ```
+
+ - **Query database**
+
+ ```bash
+ sudo -g atlas sqlite3 -readonly /var/lib/atlas/accounts.db
+ sudo -g atlas sqlite3 -readonly /var/lib/atlas/pdata.db
+ ```
+
+ - **Query database (read-write)**
+
+ ```bash
+ sudo -u atlas sqlite3 /var/lib/atlas/accounts.db
+ sudo -u atlas sqlite3 /var/lib/atlas/pdata.db
+ ```
+
+ - **Profile memory/cpu usage**
+
+ 1. Enable the debug server by adding `INSECURE_DEBUG_SERVER_ADDR=127.0.0.1:8080` to the config and restarting Atlas.
+ 2. If necessary, forward the port locally over SSH.
+ 3. Use `go tool pprof` to view the profile, for example:
+ - `go tool pprof -http : http://127.0.0.1:8080/debug/pprof/heap`
+ - `go tool pprof -http : http://127.0.0.1:8080/debug/pprof/profile?seconds=30`
+
+ - **Debug a failed Origin login**
+
+ 1. Get the latest HAR archive from `/var/log/atlas/har`.
+ 2. Uncompress it.
+ 3. Open it in a viewer like [this one](http://www.softwareishard.com/har/viewer/). Note that the network tab in browser devtools often doesn't work since they aren't fully spec-compliant.
+
+ You can reset the Origin auth state by removing `/var/lib/atlas/origin.json` and restarting Atlas.
+
+## Monitoring
+
+Sample promscrape config:
+
+```yaml
+global:
+ scrape_interval: 15s
+
+scrape_configs:
+ - job_name: 'atlas'
+ static_configs:
+ - targets:
+ - 'northstar.tf:443'
+ scheme: https
+ relabel_configs:
+ - # enable internal metrics
+ target_label: '__param_secret'
+ replacement: 'YOUR_METRICS_SECRET'
+ - # enable geohash-based metrics
+ target_label: '__param_geo'
+ replacement: 'true'
+ - # prettify the instance name
+ source_labels: ['__address__']
+ target_label: 'instance'
+ regex: '^(?:.+//)([^/:]+)'
+ replacement: '${1}'
+```
+
+Note: VictoriaMetrics generally performs better than Prometheus.
+
+<!-- TODO: sample dashboards and JSON. -->