diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..21426653 --- /dev/null +++ b/.env.example @@ -0,0 +1,2 @@ +LACUNA_MYSQL_ROOT_PASSWORD= +CONTAINER_REGISTRY_URL= diff --git a/.gitignore b/.gitignore index bdbcb96f..6f979f01 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ public/network19/ public/server/ public/captcha/ tmp/ +etc/lacuna.conf +data/ # Log tree: keep the directory skeleton (log/*/.gitkeep) but ignore the output. log/**/*.log diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..32ba2d9b --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,163 @@ +services: + beanstalk-console: + container_name: beanstalk-console + restart: unless-stopped + depends_on: + - beanstalk + image: schickling/beanstalkd-console + + beanstalk: + container_name: beanstalk + restart: unless-stopped + image: schickling/beanstalkd + + memcached: + container_name: memcached + restart: unless-stopped + image: memcached + command: + # Persist cache in a file to save sessions (and other data) between restarts of the docker container + - --memory-file=/tempfs_mount/memory_file + volumes: + - ./data/memcached:/tempfs_mount + + mysql: + container_name: mysql + platform: linux/amd64 + restart: unless-stopped + environment: + MYSQL_ROOT_PASSWORD: ${LACUNA_MYSQL_ROOT_PASSWORD:?error} + image: mysql:5.5 + volumes: + - ./data/mysql:/var/lib/mysql + healthcheck: + # mysqladmin ping exits 0 once mysqld accepts connections; passing creds + # makes it a truer check (it would also exit 0 on an auth failure). + test: ['CMD-SHELL', 'mysqladmin ping -h 127.0.0.1 -u root -p"$$MYSQL_ROOT_PASSWORD" --silent'] + interval: 10s + timeout: 5s + retries: 10 + start_period: 30s + + phpmyadmin: + container_name: phpmyadmin + image: phpmyadmin:5.2-apache + restart: unless-stopped + environment: + PMA_HOST: mysql + depends_on: + - mysql + links: + - mysql + + server: + build: + context: . + dockerfile: Dockerfile + command: '/bin/bash bin/start_lacuna.sh' + container_name: server + restart: unless-stopped + depends_on: + mysql: + condition: service_healthy + memcached: + condition: service_started + beanstalk: + condition: service_started + environment: + # Disables the prod-only size-limit / profiling middleware (bin/lacuna.psgi). + TLE_NO_MIDDLEWARE: 1 + volumes: + - ./bin:/home/lacuna/server/bin + - ./data/public-captcha:/home/lacuna/server/public/captcha + - ./data/public-missioncommand:/home/lacuna/server/public/missioncommand + - ./data/public-network19:/home/lacuna/server/public/network19 + - ./data/public-server:/home/lacuna/server/public/server + - ./etc:/home/lacuna/server/etc + - ./lib:/home/lacuna/server/lib + - ./log:/home/lacuna/server/log + - ./missions:/home/lacuna/server/missions + - ./t:/home/lacuna/server/t + - ./tmp:/tmp + - ./var:/home/lacuna/server/var + - ./cpanfile:/home/lacuna/server/cpanfile + - ./cpanfile.snapshot:/home/lacuna/server/cpanfile.snapshot + healthcheck: + # /starman_ping (bin/lacuna.psgi) returns "pong" only once the Lacuna app + # has compiled and Starman is serving requests. curl is in the server image. + test: ['CMD', 'curl', '-fsS', 'http://localhost:5000/starman_ping'] + interval: 15s + timeout: 10s + retries: 5 + start_period: 180s + + server-building-scheduler: + build: + context: . + dockerfile: Dockerfile + command: '/bin/bash bin/run_scheduler.sh schedule_building.pl --noquiet --nodaemonize --initialize' + container_name: server-building-scheduler + restart: unless-stopped + depends_on: + server: + condition: service_healthy + volumes: + - ./tmp:/tmp + - ./log:/home/lacuna/server/log + - ./etc:/home/lacuna/server/etc + + server-ship-scheduler: + build: + context: . + dockerfile: Dockerfile + command: '/bin/bash bin/run_scheduler.sh schedule_ship_arrival.pl --noquiet --nodaemonize --initialize' + container_name: server-ship-scheduler + restart: unless-stopped + depends_on: + server: + condition: service_healthy + volumes: + - ./tmp:/tmp + - ./log:/home/lacuna/server/log + - ./etc:/home/lacuna/server/etc + + server-captcha-scheduler: + build: + context: . + dockerfile: Dockerfile + command: '/bin/bash bin/run_scheduler.sh schedule_captcha.pl --noquiet --nodaemonize' + container_name: server-captcha-scheduler + restart: unless-stopped + depends_on: + server: + condition: service_healthy + volumes: + - ./tmp:/tmp + - ./log:/home/lacuna/server/log + - ./etc:/home/lacuna/server/etc + + server-script-scheduler: + container_name: server-script-scheduler + image: mcuadros/ofelia:latest + restart: unless-stopped + depends_on: + server: + condition: service_healthy + command: daemon + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - ./schedule.ini:/etc/ofelia.conf + + v2-api: + image: ${CONTAINER_REGISTRY_URL:?error}/tlecommunity/v2-api:latest + restart: unless-stopped + container_name: v2-api + command: node index.ts + environment: + PORT: 5999 + +networks: + default: + name: lacuna + +name: lacuna diff --git a/etc/lacuna.example.conf b/etc/lacuna.example.conf new file mode 100644 index 00000000..058d4098 --- /dev/null +++ b/etc/lacuna.example.conf @@ -0,0 +1,123 @@ +# config-file-type: JSON 1 +{ + # Ensure both of these have trailing slashes! + "server_url": "http://localhost:5000/", + "assets_url": "https://assets.tlecommunity.com/", + + "develop_mode": 0, + "offline": 0, + + "rpc_limit": 10000, + "rpc_throttle": 200, + "self_destruct_after_inactive_days": 9999999, + + "bhg_param": { + # If any are set to 0, use default. + "success": 0, + "waste_cost": 0, + "recovery": 0, + "side_chance": 0, + }, + + "beanstalk": { + "debug": 0, + "server": "beanstalk:11300", + "ttr": 120, + "max_timeouts": 10, + "max_reserves": 10 + }, + + "captcha": { + # path to the fonts being used. + "fontpath": "/home/lacuna/server/var/fonts", + # .ttf fonts in above path + "fonts": [ + "Ayuthaya", + "Chalkduster", + "Caveat", + "EduNSWACTCursive", + "Merienda", + "PermanentMarker", + "PlaywriteAUQLD" + ], + }, + + "db": { + "dsn": "DBI:mysql:host=mysql;database=lacuna", + "password": "lacuna", + "username": "root" + }, + + "feeds": { + "url": "http://localhost:5000" + }, + + "mailgun": { + "api_key": "XXXX", + }, + + "map_size": { + "x": [-50, 50], + "y": [-50, 50] + }, + + "memcached": [ + { + "host": "memcached", + "port": "11211" + } + ], + + # If zone is set to a valid zone, x & y are confined to within that zone. + # Coord set to 1 will further narrow Neutral area. + # Setting zone to 0 will only use x & y. + # Setting x & y outside of the zone, will result in nothing be within the NZ. + # If only coord is set, then zone boundaries are ignored. + "neutral_area": { + "active": 0, + "zone": 0, + "zone_list": ["-1|0"], + "coord": 0, + "x": [-1000, -750], + "y": [-250, 250] + }, + + # Required to remember essentia amounts after empires are deleted + # Note that none of this will work as we don't have the code for the + # "essentia server" and it doesn't look like the empire implementation + # will handle those API calls failing. + "essentia_code_server_url": "", + "server_key": "XXXX", + + # Required for essentia codes to work + "server_keys": [ + "XXXX" + ], + + # If zone is set to a valid zone, x & y are confined to within that zone. + # Coord set to 1 will further narrow area. + # Setting zone to 0 will only use x & y. + # Setting x & y outside of the zone, will result in nothing be within the NZ. + # If only coord is set, then zone boundaries are ignored. + "starter_zone": { + "active": 1, + # "max_colonies" : 2, + "zone": 1, + "zone_list": [ + "0|0" + # "-1|-1", + # "-1|1", + # "1|-1", + # "1|1" + ], + "coord": 0, + "x": [ -50, 50 ], + "y": [ -50, 50 ] + }, + + # Entertainment District lottery voting options + "voting_sites": [ + { "name": "Natalie Rose", "url": "https://nataliethistime.com/" }, + { "name": "TLE Community", "url": "https://tlecommunity.com/" } + ] +} diff --git a/etc/log4perl.conf b/etc/log4perl.conf new file mode 100644 index 00000000..d70b27bd --- /dev/null +++ b/etc/log4perl.conf @@ -0,0 +1,19 @@ +# Production logging. INFO (not DEBUG) is the only difference from etc-dev: it +# keeps the per-request RPC line (lib/Lacuna/RPC.pm, $log->info) but drops the +# DEBUG chatter, to bound disk. SCREEN -> `docker logs server`; FILE -> +# host-mounted log/server/lacuna.log, rotated by the logrotate sidecar. +log4perl.logger = INFO, SCREEN, FILE + +log4perl.appender.SCREEN = Log::Log4perl::Appender::Screen +log4perl.appender.SCREEN.stderr = 1 +log4perl.appender.SCREEN.layout = Log::Log4perl::Layout::SimpleLayout + +log4perl.appender.FILE = Log::Log4perl::Appender::File +log4perl.appender.FILE.filename = /home/lacuna/server/log/server/lacuna.log +log4perl.appender.FILE.mode = append +log4perl.appender.FILE.mkpath = 1 +log4perl.appender.FILE.autoflush = 1 +log4perl.appender.FILE.recreate = 1 +log4perl.appender.FILE.recreate_check_interval = 30 +log4perl.appender.FILE.layout = Log::Log4perl::Layout::PatternLayout +log4perl.appender.FILE.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} [%p] %m%n