Compare commits

..

9 Commits

Author SHA1 Message Date
03c7277692 Fix ionos-dyndns timer interval
All checks were successful
Check / Lint Ansible Files (push) Successful in 2m29s
systemd uses min, not m for minutes.
2023-11-20 21:45:13 +01:00
de16857570 Remove unused leftover variable 2023-11-19 03:38:50 +01:00
f2f12a2688 Add agenix, spigot-server and ionos-dyndns to gilgamesh config
All checks were successful
Check / Lint Ansible Files (push) Successful in 3m1s
2023-11-19 03:09:42 +01:00
e61a07f8d3 Add ionos-dyndns module for the NixOS config 2023-11-19 03:05:31 +01:00
ea38d94178 Add runtime dependencies to ionos-dyndns package 2023-11-19 03:04:52 +01:00
81771725d0 Add agenix secrets for IONOS dyndns 2023-11-19 03:04:01 +01:00
06345cd04c Add agenix to dev flake 2023-11-19 02:59:34 +01:00
9b622e6e3e Number of fixes
All checks were successful
Check / Lint Ansible Files (push) Successful in 1m40s
Package IONOS-DynDNS repository

Fix spigot-server's ExecStop

Enable Firewall but allow port 25565
2023-11-18 13:44:10 +01:00
8e0c6266af Add gilgamesh NixOS config and spigot-server package
All checks were successful
Check / Lint Ansible Files (push) Successful in 2m18s
2023-11-18 05:28:33 +01:00
56 changed files with 1005 additions and 200 deletions

View File

@ -1,16 +1,15 @@
name: Check
"on": [push]
on: [push]
jobs:
"Lint Ansible Files":
runs-on: node-22-bookworm
runs-on: ubuntu-22.04
steps:
- run: apt-get update
- run: apt-get upgrade -y
- run: apt-get install -y python3 python3-pip python3-venv
- run: python3 --version
- name: Check out repo
uses: actions/checkout@v3
- run: python3 -m venv venv
- run: venv/bin/pip --disable-pip-version-check install ansible==11.1.0 ansible-lint==24.12.1
- run: venv/bin/pip --disable-pip-version-check install ansible==7.2.0 ansible-lint==6.16.1 > /dev/null 2> /dev/null
- run: venv/bin/ansible-lint -c .ansible-lint ansible
# TODO: Reimplement ansible-play --check step from old drone config

View File

@ -4,8 +4,8 @@
| Prop | Value |
| --- | --- |
| Hostname | `nanna` |
| Domains | `{,pad.,codi.,git.,plantuml.}pbrinkmeier.de`, `tichy.click`, `{utoy,vrnp}.beany.club` |
| Hostname | `shamash` |
| Domains | `{,pad.,codi.,ci.,git.,jupyter.,plantuml.}pbrinkmeier.de`, `tichy.click`, `beany.club`, `vmd98928.contaboserver.net` |
## Linting
@ -17,7 +17,3 @@ ansible-lint --offline
```
to avoid checking for a new version every single run.
## TODO
- [x] Migrate to `community.docker.docker_compose_v2` (`v1` is deprecated)

View File

@ -12,11 +12,11 @@ nix develop
## `misc.yaml`
Server for miscellaneous stuff, e.g. the website.
Expects to have a user `paul who can `sudo`.
Expects to have a user `andi` who can `sudo`.
Sets up:
- Some basic packages
- Docker and `docker-compose`
- Docker and `docker-compose` (the latter via `pip`)
- Nix multi-user installation
## `misc-docker.yaml`

View File

@ -1,15 +0,0 @@
---
ansible_python_interpreter: /usr/bin/python3
gods_users:
- name: postgres
uid: 70
state: present
- name: hackmd
uid: 1500
state: present
- name: gitea
uid: 42001
state: present
- name: caddy
uid: 42002
state: present

View File

@ -0,0 +1,4 @@
---
# Has pw-less sudo
ansible_user: paul
ansible_python_interpreter: /usr/bin/python3

View File

@ -1,8 +0,0 @@
$ANSIBLE_VAULT;1.1;AES256
37646262396235383766303137613134323330396364346261653036303935663935323930663630
3562306337383765323635623838646538376362396638360a366336336134616163663533373836
30333834306466633162613264376266646239343432646162396132643437663934613464363437
6530653234336133360a666232386537353835386364613065343063613536613638393736666635
65363362363766353231646461343764306637353465373633363861333436336263393561656330
39613761373437313663613737613961666330373135666365373433376437383232383461633861
333763383538633430303663636338363537

View File

@ -1,2 +1,2 @@
[gods]
nanna
[misc]
vmd98928.contaboserver.net ansible_port=2309

View File

@ -0,0 +1,8 @@
# All tasks for misc, use this to check whether everything is deployed.
---
- name: Set up basic packages, Docker, Nix, sshd
import_playbook: misc-setup.yaml
- name: Deploy Docker configuration
import_playbook: misc-docker.yaml
- name: Check out static websites from git
import_playbook: misc-sites.yaml

View File

@ -1,25 +1,39 @@
---
- name: Update Docker configuration
hosts: gods
- name: Update Docker configuration on shamash
hosts: misc
tasks:
- name: Add groups
become: true
ansible.builtin.group:
name: "{{ item.name }}"
gid: "{{ item.uid }}"
state: "{{ item.state }}"
system: true
loop: "{{ gods_users }}"
- name: Add users for running containers
become: true
ansible.builtin.user:
name: "{{ item.name }}"
uid: "{{ item.uid }}"
group: "{{ item.name }}"
state: "{{ item.state }}"
create_home: false
system: true
loop: "{{ gods_users }}"
loop:
- name: jupyter
uid: 42000
state: present
- name: gitea
uid: 42001
state: present
- name: score
uid: 42003
state: present
- name: factorio
uid: 845
state: present
- name: hackmd
uid: 1500
state: present
- name: hedgedoc
uid: 10000
state: absent
- name: bsa
uid: 42002
state: absent
# All services that are behind Caddy need to be in this network
- name: Create Caddy network
become: true
community.docker.docker_network:
@ -34,13 +48,6 @@
mode: u=rw,g=,o=
# Directories should be listable
directory_mode: u=rwx,g=rx,o=rx
- name: Create directory for docker volumes
become: true
ansible.builtin.file:
path: /var/lib/pbri/docker
state: directory
# Hide contents from non-root users
mode: u=rwx,g=,o=
- name: Upload and decrypt docker environment vars
become: true
ansible.builtin.copy:
@ -51,18 +58,24 @@
# This is true by default but I put it here anyways
# to emphasize what's happening
decrypt: true
# Not quite happy with all the seperate loops yet.
loop:
- name: gitea
state: present
- name: codi
state: present
- name: vrnp
- name: drone
state: present
- name: zomboid
- name: factorio
state: present
# This needs to be done for any services where user:
# is set in docker-compose.yaml.
- name: Create volume directories with correct permissions
- name: gitea
state: present
- name: Create directory for docker volumes
become: true
ansible.builtin.file:
path: /var/lib/pbri/docker
state: directory
# Hide contents from non-root users
mode: u=rwx,g=,o=
- name: Create jupyter folders
become: true
ansible.builtin.file:
path: "/var/lib/pbri/docker/{{ item.name }}"
@ -71,22 +84,36 @@
state: directory
mode: u=rwx,g=,o=
loop:
- name: caddy_config
user: caddy
- name: caddy_data
user: caddy
- name: codi_uploads
user: hackmd
- name: jupyter_data
user: jupyter
- name: jupyter_notebooks
user: jupyter
- name: Create Factorio data folder
become: true
ansible.builtin.file:
path: /var/lib/pbri/docker/factorio
state: directory
owner: factorio
group: factorio
mode: u=rwx,g=,o=
- name: Create score data folder
become: true
ansible.builtin.file:
path: /var/lib/pbri/docker/score
state: directory
owner: score
group: score
mode: u=rwx,g=,o=
# Since some docker-compose configuration might want to pull
# images from the Gitea package repository, we need to ensure
# that Gitea is reachable before those configurations are deployed.
- name: Set up caddy and gitea containers
become: true
community.docker.docker_compose_v2:
community.docker.docker_compose:
project_src: "/etc/pbri/docker/{{ item.name }}"
state: "{{ item.state }}"
build: "always"
pull: "always"
build: true
debug: true
loop:
- name: caddy
state: present
@ -102,20 +129,27 @@
register: gitea_version_response
until: gitea_version_response.status == 200
retries: 10
delay: 3 # Retry every 3 seconds
delay: 5 # Retry every 5 seconds
- name: Set up other containers
become: true
community.docker.docker_compose_v2:
community.docker.docker_compose:
project_src: "/etc/pbri/docker/{{ item.name }}"
state: "{{ item.state }}"
build: "always"
pull: "always"
build: true
debug: true
loop:
- name: drone
state: present
- name: codi
state: present
- name: jupyter
state: present
- name: utoy
state: present
- name: vrnp
state: present
- name: zomboid
- name: score
state: present
- name: factorio
state: absent
- name: glebby
state: absent

View File

@ -0,0 +1,74 @@
---
- name: Basic setup for shamash (packages, Docker, Nix, sshd)
hosts: misc
tasks:
- name: Create /etc/pbri
become: true
ansible.builtin.file:
path: /etc/pbri
state: directory
mode: u=rwx,g=rx,o=rx
- name: Create /home/paul/{Sites,Source}
become: true
ansible.builtin.file:
path: "/home/paul/{{ item }}"
state: directory
owner: paul
group: paul
mode: u=rwx,g=rx,o=rx
loop:
- Sites
- Source
- name: Install basic packages
become: true
ansible.builtin.apt:
name:
- vim
- git
- htop
- tmux
update_cache: true
tags:
- apt
- name: Install and set up Docker and docker-compose
ansible.builtin.include_role:
name: docker
- name: Install and set up Nix
ansible.builtin.include_role:
name: install_nix
- name: Install pip prerequisites
become: true
ansible.builtin.apt:
name:
- python3-pip
- python3-setuptools
- python3-virtualenv
- name: Install global python docker package
become: true
ansible.builtin.pip:
name:
- docker
- docker-compose
- requests
- name: Configure sshd
become: true
ansible.builtin.copy:
dest: /etc/ssh/sshd_config.d/00_pbri.conf
mode: u=rw,g=r,o=r
# Included by /etc/ssh/sshd_config before other configuration
content: |
Port 2309
PermitRootLogin no
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication no
validate: /usr/sbin/sshd -T -f %s
notify:
- Restart sshd
handlers:
- name: Restart sshd
become: true
ansible.builtin.service:
name: sshd
state: restarted

View File

@ -1,16 +1,16 @@
---
- name: Check out static sites hosted on nanna
hosts: nanna
- name: Check out static sites hosted on shamash
hosts: misc
tasks:
- name: Check out static sites
ansible.builtin.include_role:
name: checkout_static_sites
vars:
checkout_static_sites_config:
checkout_static_sites:
checkouts:
- path: /home/paul/Sites/pbrinkmeier.de
url: https://git.pbrinkmeier.de/paul/pbrinkmeier.de
commit: bab3208e61972851a5e609930a05e0d4322f8a06
commit: 680ac7d9c44752f57436d0ecb9c8018205a5fc0f
owner: paul
- path: /home/paul/Sites/tichy.click
url: https://github.com/pbrinkmeier/tichy-clicker

View File

@ -1,29 +0,0 @@
---
- name: Basic setup for nanna
hosts: nanna
tasks:
- name: Configure sshd
become: true
ansible.builtin.copy:
dest: /etc/ssh/sshd_config.d/00_pbri.conf
mode: u=rw,g=r,o=r
# Included by /etc/ssh/sshd_config before other configuration
content: |
Port 2309
PermitRootLogin no
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication no
validate: /usr/sbin/sshd -T -f %s
notify:
- Restart sshd
- name: Install and set up Docker and docker-compose
ansible.builtin.include_role:
name: docker
handlers:
- name: Restart sshd
become: true
ansible.builtin.service:
name: ssh
state: restarted

View File

@ -7,7 +7,7 @@
mode: '0755'
owner: "{{ item.owner }}"
group: "{{ item.owner }}"
loop: "{{ checkout_static_sites_config.checkouts }}"
loop: "{{ checkout_static_sites.checkouts }}"
- name: Check out static site repositories
become: true
become_user: "{{ item.owner }}"
@ -15,5 +15,4 @@
dest: "{{ item.path }}"
repo: "{{ item.url }}"
version: "{{ item.commit }}"
force: true
loop: "{{ checkout_static_sites_config.checkouts }}"
loop: "{{ checkout_static_sites.checkouts }}"

View File

@ -1,3 +0,0 @@
---
docker_apt_arch: "amd64"
docker_ubuntu_release: "{{ ansible_distribution_release }}"

View File

@ -25,6 +25,12 @@
stdin: "{{ docker_gpg_key.content }}"
creates: /usr/share/keyrings/docker-archive-keyring.gpg
- name: Retrieve dpkg architecture
check_mode: false
ansible.builtin.command: dpkg --print-architecture
register: docker_dpkg_architecture
changed_when: false
- name: Add Docker apt repository
become: true
ansible.builtin.template:
@ -42,4 +48,3 @@
- docker-ce
- docker-ce-cli
- containerd.io
- docker-compose-plugin

View File

@ -1 +1 @@
deb [arch={{ docker_apt_arch }} signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu {{ docker_ubuntu_release }} stable
deb [arch={{ docker_dpkg_architecture.stdout }} signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable

View File

@ -45,6 +45,6 @@ utoy.beany.club {
reverse_proxy utoy:3000
}
vrnp.beany.club {
reverse_proxy vrnp:8000
score.brocke.net {
reverse_proxy score:8080
}

View File

@ -1,4 +1,3 @@
FROM caddy
COPY Caddyfile /etc/caddy/Caddyfile
RUN chown 42002:42002 /etc/caddy/Caddyfile

View File

@ -1,3 +1,5 @@
version: "3"
services:
# Webserver for static files and reverse proxy
web:
@ -6,7 +8,6 @@ services:
ports:
- "80:80"
- "443:443"
user: "42002"
volumes:
- /var/lib/pbri/docker/caddy_data:/data
- /var/lib/pbri/docker/caddy_config:/config

View File

@ -1,6 +1,8 @@
version: "3"
services:
codi:
image: hackmdio/hackmd:2.5.4
image: hackmdio/hackmd:2.4.2
user: hackmd
environment:
# Admin stuff

View File

@ -0,0 +1,9 @@
Add a `.env` file like this:
```
DRONE_GITEA_CLIENT_ID=...
DRONE_GITEA_CLIENT_SECRET=...
DRONE_RPC_SECRET=...
```
See also: https://docs.drone.io/server/provider/gitea/.

View File

@ -0,0 +1,32 @@
version: "3"
services:
drone:
image: drone/drone:2
environment:
DRONE_GITEA_SERVER: https://git.pbrinkmeier.de
DRONE_GITEA_CLIENT_ID: "${DRONE_GITEA_CLIENT_ID}"
DRONE_GITEA_CLIENT_SECRET: "${DRONE_GITEA_CLIENT_SECRET}"
DRONE_RPC_SECRET: "${DRONE_RPC_SECRET}"
DRONE_SERVER_HOST: ci.pbrinkmeier.de
DRONE_SERVER_PROTO: https
volumes:
- /var/lib/pbri/docker/drone:/data
restart: unless-stopped
drone_runner:
image: drone/drone-runner-docker:1
environment:
DRONE_RPC_PROTO: https
DRONE_RPC_HOST: ci.pbrinkmeier.de
DRONE_RPC_SECRET: "${DRONE_RPC_SECRET}"
DRONE_RUNNER_CAPACITY: 1
DRONE_RUNNER_NAME: shamash
volumes:
- /var/run/docker.sock:/var/run/docker.sock
restart: unless-stopped
networks:
default:
name: caddy-network
external: true

View File

@ -0,0 +1,4 @@
FROM factoriotools/factorio:1.1.87
COPY server-settings.json /server-settings.json
ENTRYPOINT [ "/bin/sh", "-c", "mkdir -p /factorio/config && envsubst < /server-settings.json > /factorio/config/server-settings.json && exec /docker-entrypoint.sh" ]

View File

@ -0,0 +1,10 @@
# factorio
Add a `.env` file like this:
```
GAME_PASSWORD=...
```
Environment variables are put into `server-settings.json` during startup using `envsubst`.
See also: https://hub.docker.com/r/factoriotools/factorio.

View File

@ -0,0 +1,14 @@
version: "3"
services:
gitea:
image: pbrinkmeier/factorio
build: .
restart: always
environment:
GAME_PASSWORD: "${GAME_PASSWORD}"
volumes:
- /var/lib/pbri/docker/factorio:/factorio
ports:
- "34197:34197/udp"
- "27015:27015/tcp"

View File

@ -0,0 +1,72 @@
{
"name": "le epic factorio server",
"description": "Description of the game that will appear in the listing",
"tags": ["game", "tags"],
"_comment_max_players": "Maximum number of players allowed, admins can join even a full server. 0 means unlimited.",
"max_players": 0,
"_comment_visibility": ["public: Game will be published on the official Factorio matching server",
"lan: Game will be broadcast on LAN"],
"visibility":
{
"public": false,
"lan": false
},
"_comment_credentials": "Your factorio.com login credentials. Required for games with visibility public",
"username": "",
"password": "",
"_comment_token": "Authentication token. May be used instead of 'password' above.",
"token": "",
"game_password": "",
"_comment_require_user_verification": "When set to true, the server will only allow clients that have a valid Factorio.com account",
"require_user_verification": false,
"_comment_max_upload_in_kilobytes_per_second" : "optional, default value is 0. 0 means unlimited.",
"max_upload_in_kilobytes_per_second": 0,
"_comment_max_upload_slots" : "optional, default value is 5. 0 means unlimited.",
"max_upload_slots": 5,
"_comment_minimum_latency_in_ticks": "optional one tick is 16ms in default speed, default value is 0. 0 means no minimum.",
"minimum_latency_in_ticks": 0,
"_comment_max_heartbeats_per_second": "Network tick rate. Maximum rate game updates packets are sent at before bundling them together. Minimum value is 6, maximum value is 240.",
"max_heartbeats_per_second": 60,
"_comment_ignore_player_limit_for_returning_players": "Players that played on this map already can join even when the max player limit was reached.",
"ignore_player_limit_for_returning_players": false,
"_comment_allow_commands": "possible values are, true, false and admins-only",
"allow_commands": "admins-only",
"_comment_autosave_interval": "Autosave interval in minutes",
"autosave_interval": 10,
"_comment_autosave_slots": "server autosave slots, it is cycled through when the server autosaves.",
"autosave_slots": 5,
"_comment_afk_autokick_interval": "How many minutes until someone is kicked when doing nothing, 0 for never.",
"afk_autokick_interval": 5,
"_comment_auto_pause": "Whether should the server be paused when no players are present.",
"auto_pause": true,
"only_admins_can_pause_the_game": true,
"_comment_autosave_only_on_server": "Whether autosaves should be saved only on server or also on all connected clients. Default is true.",
"autosave_only_on_server": true,
"_comment_non_blocking_saving": "Highly experimental feature, enable only at your own risk of losing your saves. On UNIX systems, server will fork itself to create an autosave. Autosaving on connected Windows clients will be disabled regardless of autosave_only_on_server option.",
"non_blocking_saving": false,
"_comment_segment_sizes": "Long network messages are split into segments that are sent over multiple ticks. Their size depends on the number of peers currently connected. Increasing the segment size will increase upload bandwidth requirement for the server and download bandwidth requirement for clients. This setting only affects server outbound messages. Changing these settings can have a negative impact on connection stability for some clients.",
"minimum_segment_size": 25,
"minimum_segment_size_peer_count": 20,
"maximum_segment_size": 100,
"maximum_segment_size_peer_count": 10
}

View File

@ -1,3 +1,3 @@
FROM gitea/act_runner:0.2.11
FROM gitea/act_runner:0.2.5
COPY runner-config.yaml /opt/runner-config.yaml

View File

@ -1,6 +1,8 @@
version: "3"
services:
gitea:
image: gitea/gitea:1.23.1
image: gitea/gitea:1.20.3
restart: unless-stopped
environment:
# Ref: https://docs.gitea.io/en-us/config-cheat-sheet
@ -64,8 +66,7 @@ services:
- /var/lib/pbri/docker/gitea_db:/var/lib/postgresql/data
gitea_runner:
# Make sure to keep this in sync with the version in the Dockerfile
image: pbrinkmeier/act_runner:0.2.11
image: pbrinkmeier/act_runner:0.2.5
build: .
restart: unless-stopped
environment:

View File

@ -32,8 +32,6 @@ runner:
# ubuntu:22.04 here is not enough.
labels:
- "ubuntu-22.04:docker://node:16-bullseye"
- "node-22-bullseye:docker://node:22-bullseye"
- "node-22-bookworm:docker://node:22-bookworm"
cache:
# Enable cache server to use actions/cache.

View File

@ -0,0 +1,11 @@
version: "3"
services:
glebby:
image: git.pbrinkmeier.de/paul/glebby:1.1-prod
restart: always
networks:
default:
name: caddy-network
external: true

View File

@ -0,0 +1,15 @@
version: "3"
services:
jupyter:
image: git.pbrinkmeier.de/paul/jup:1.5
user: "42000"
volumes:
- /var/lib/pbri/docker/jupyter_data:/data
- /var/lib/pbri/docker/jupyter_notebooks:/notebooks
restart: always
networks:
default:
name: caddy-network
external: true

View File

@ -0,0 +1,16 @@
version: "3"
services:
score:
image: ghcr.io/lbrocke/score:v1.0.2
user: "42003:42003"
environment:
SCORE_LISTEN: 0.0.0.0:8080
volumes:
- /var/lib/pbri/docker/score:/data
restart: unless-stopped
networks:
default:
name: caddy-network
external: true

View File

@ -1,3 +1,5 @@
version: "3"
services:
utoy:
image: git.pbrinkmeier.de/paul/utoy:0.6

View File

@ -1,11 +0,0 @@
services:
vrnp:
image: git.pbrinkmeier.de/paul/vrnp:0.0.3
restart: always
environment:
VRNP_PASSWORD: "${VRNP_PASSWORD}"
networks:
default:
name: caddy-network
external: true

View File

@ -1,15 +0,0 @@
services:
zomboid:
image: renegademaster/zomboid-dedicated-server:2.5.0
restart: unless-stopped
volumes:
- /var/lib/pbri/docker/zomboid_dedicated_server:/home/steam/ZomboidDedicatedServer
- /var/lib/pbri/docker/zomboid_config:/home/steam/Zomboid
ports:
- "16261:16261/udp"
- "16262:16262/udp"
environment:
ADMIN_USERNAME: "the_gwiddy"
ADMIN_PASSWORD: "${ZOMBOID_ADMIN_PASSWORD}"
SERVER_NAME: "gwiddy time"
SERVER_PASSWORD: "${ZOMBOID_SERVER_PASSWORD}"

14
docker/envs/drone/.env Normal file
View File

@ -0,0 +1,14 @@
$ANSIBLE_VAULT;1.1;AES256
31333834393366333930346366373931333930646233383664643463393965303238613430646638
6461373434616433353337643131396462326537346434380a386562633335346436303662336362
62333739626237323334333666633162616338313932393261303231353539623237383638643030
3364393934653232310a383065386530373433393635313665353532666361303436613337316565
32306233336134383531633232393862303466373331373764376462653736663861663366323762
65666263366461396362386264613830336435346234386234333562616131653938386439336566
34386461343433346363336161373038303434383563303564653533623939613937323030636362
66636639643963613236366138646335393831366432333637333065326162646237643561336666
61323833333337633861646462393930663733333266336233663630396532366566303835653431
38363365383166393765343735363030363562313837643837313864373735643264663264643633
66306261633666616363666562306632613032373231633730313638383033633761653661383738
39623630643766663438656635653530626664313765633430646330356333306239653437373839
3933

View File

@ -0,0 +1,7 @@
$ANSIBLE_VAULT;1.1;AES256
32356463313330336636636363646138393236636233326132623165353962623565356364396530
3636336532396665333637653432353332643434643962390a313162343836306435383536313937
36656632356366303561366536373535383538303730386239386437323466346533353634306436
3930633464353235360a653936333734353137313363316261366666353238366566613865366463
32393431343439383733343766323831643561663938376264336331306139646337343633346536
3236343538323032636666366639303539316236393535323661

View File

@ -1,14 +1,14 @@
$ANSIBLE_VAULT;1.1;AES256
30626565616334613665623138613533653739333038643530636633393264393334373563326631
3838333663306537326534333666316539383038363236650a613163643433653466666639666366
33653861613638653862393338386334643332633762666136613932343834333162303363373030
6161323863316134340a646532386537313164643039353435633535363061616363363337663365
39343461356631383062353837383034653430373663323966373632323063636132613137643662
37373065313764626539396463376637353136613365366566363436356537343932376565633962
62316631663634316530623736613961623635303763633964386433333531626437303136363537
35393134643935316330396161303134626537643162393062636363376435636162393136373034
39636231626635643530313634333464653564353861656666633035623932336234303735386366
62303133326237613763336435323338623036663137333439613462333434303734303737363936
65333762376233396332633434353832373136383137336665623534356538636166303835376334
64346139656432633230386666653531333864333664393936366630346334323963343431346164
64376165666230386464303036303861653437646463633764343064376464396135
35623364633833623964623536646534373634663736613561333561343136333965306638396532
6162393239383936386338666565306132646230383066630a336337613636383431623738343663
61343262363631376665383035323139313863626331666439336134613035663439376231343863
3032353139643138640a383365356630323835383538393734643134343133653033383663333464
62386361633435633664306531623835353665326432393932336163316561653866343137323030
63643262323436356166373533363235366238393633336631336266373837373932313134303563
65633337393938623134636538653561356565333831356638373862376333336163363438626438
39343436383732313561396236656530303064363961663636353538346264633532633866333162
35303032303662646166333537373566316462633536333463323433353539623363323036643763
34376365613932303133366236613235636238643139666663356436326532616437383432303437
39376535656266383465373837643634383937656431323265386163373138336164383666383962
64623762613332363731323739666238613634646237396331666463363663313461313966356233
30653362353061333739303234336461373337346632646433623462623765353330

View File

@ -1,10 +0,0 @@
$ANSIBLE_VAULT;1.1;AES256
36643163613366383136326339346231373533373361633834663332343932356665303434333564
3936636366396233326664636137363134643066303432380a363662646465656130303431386530
37316138366239313038336664313661333632393333666539363565623032653431623935613631
3635323330363663610a353263663736653561666261636138336438666261613739346664393233
32323364346665633662663266626436343831386565663761393237346637376438613865363663
36613035376638653937633866613935343834633431393830303438363265656337343565323063
36303033323537666236633037656236656133396431326362303462353237326162626335363761
36636362306232333630613464393135383539666632343038393333353462336238663130326166
3061

View File

@ -1,10 +0,0 @@
$ANSIBLE_VAULT;1.1;AES256
35336632386231333233333633656163356564316637366438383532626437303364633733353436
3836376461393761653637666532643264613864633935620a326365386634393935333433306564
62346235346262313339633739353232663562623562616136623838386233633136383764666536
6239663264643333370a393762636231343034643133613163626239353735363037646638633933
62376165306438653537343564376536396537666534633330666163346533313434616561306434
63313035643732303863663430303936346264626637623936343763303738623865356536306365
32623164323738663065613332656465643536633933643731366139626165636230343966383839
64343961316139313931313966356430343438376461366537356337363835623637306539646265
32376562363061643630663937663064393664663766613365363439653030393239

94
flake.lock generated
View File

@ -1,15 +1,57 @@
{
"nodes": {
"agenix": {
"inputs": {
"darwin": "darwin",
"home-manager": "home-manager",
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1696775529,
"narHash": "sha256-TYlE4B0ktPtlJJF9IFxTWrEeq+XKG8Ny0gc2FGEAdj0=",
"owner": "ryantm",
"repo": "agenix",
"rev": "daf42cb35b2dc614d1551e37f96406e4c4a2d3e4",
"type": "github"
},
"original": {
"owner": "ryantm",
"repo": "agenix",
"type": "github"
}
},
"darwin": {
"inputs": {
"nixpkgs": [
"agenix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1673295039,
"narHash": "sha256-AsdYgE8/GPwcelGgrntlijMg4t3hLFJFCRF3tL5WVjA=",
"owner": "lnl7",
"repo": "nix-darwin",
"rev": "87b9d090ad39b25b2400029c64825fc2a8868943",
"type": "github"
},
"original": {
"owner": "lnl7",
"ref": "master",
"repo": "nix-darwin",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"lastModified": 1685518550,
"narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
"type": "github"
},
"original": {
@ -18,13 +60,50 @@
"type": "github"
}
},
"home-manager": {
"inputs": {
"nixpkgs": [
"agenix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1682203081,
"narHash": "sha256-kRL4ejWDhi0zph/FpebFYhzqlOBrk0Pl3dzGEKSAlEw=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "32d3e39c491e2f91152c84f8ad8b003420eab0a1",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "home-manager",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1737753628,
"narHash": "sha256-vwRbCpftG6/QrBeu3eQO1l5wzAg/pAMdvGOOLeXWeM4=",
"lastModified": 1677676435,
"narHash": "sha256-6FxdcmQr5JeZqsQvfinIMr0XcTyTuR7EXX0H3ANShpQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a08d6979dd7c82c4cef0dcc6ac45ab16051c1169",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1686259070,
"narHash": "sha256-bJ2TqJHMdU27o3+AlYzsDooUzneFHwvK5LaRv5JYit4=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "f22b0184bd0f4bb3061580b1e807feb68a85d90d",
"rev": "8a7d5c039cacc83bd1926aaabc04d541e04a1460",
"type": "github"
},
"original": {
@ -35,8 +114,9 @@
},
"root": {
"inputs": {
"agenix": "agenix",
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
"nixpkgs": "nixpkgs_2"
}
},
"systems": {

View File

@ -5,9 +5,10 @@
# lib
nixpkgs.url = github:nixos/nixpkgs;
flake-utils.url = github:numtide/flake-utils;
agenix.url = github:ryantm/agenix;
};
outputs = { self, nixpkgs, flake-utils }: flake-utils.lib.eachDefaultSystem (system:
outputs = { self, nixpkgs, flake-utils, agenix }: flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
@ -16,6 +17,7 @@
buildInputs = [
pkgs.ansible
pkgs.ansible-lint
agenix.packages.${system}.default
];
shellHook = ''

12
nix/gilgamesh/README.md Normal file
View File

@ -0,0 +1,12 @@
# `gilgamesh`
> Old Thinkpad running a Minecraft server.
## TODO
- Figure out if there's some more powersaving options
- Add some doc for initial setup
- Install NixOS according to the official guide
- Check out this repo, build this `configuration.nix`
- Afterwards: Just build it locally then deploy
- Use Flakes, add doc for `./deploy.sh`

View File

@ -0,0 +1,146 @@
{ config, pkgs, lib, ... }:
let
agenix = builtins.fetchTarball {
url = "https://github.com/ryantm/agenix/archive/daf42cb35b2dc614d1551e37f96406e4c4a2d3e4.tar.gz";
sha256 = "0gbn01hi8dh7s9rc66yawnmixcasadf20zci4ijzpd143ph492ad";
};
in {
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
"${agenix}/modules/age.nix"
../modules/spigot-server.nix
../modules/ionos-dyndns.nix
];
# Use the GRUB 2 boot loader.
boot.loader.grub.enable = true;
# boot.loader.grub.efiSupport = true;
# boot.loader.grub.efiInstallAsRemovable = true;
# boot.loader.efi.efiSysMountPoint = "/boot/efi";
# Define on which hard drive you want to install Grub.
boot.loader.grub.device = "/dev/sda";
networking.hostName = "gilgamesh"; # Define your hostname.
# Pick only one of the below networking options.
# networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.
# networking.networkmanager.enable = true; # Easiest to use and most distros use this by default.
# Set your time zone.
time.timeZone = "Europe/Berlin";
# Configure network proxy if necessary
# networking.proxy.default = "http://user:password@proxy:port/";
# networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
# Select internationalisation properties.
i18n.defaultLocale = "en_US.UTF-8";
console = {
font = "Lat2-Terminus16";
keyMap = "de-latin1";
};
# Define a user account. Don't forget to set a password with passwd.
users.users.paul = {
isNormalUser = true;
extraGroups = [ "wheel" ]; # Enable sudo for the user.
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIMFqREiw3EareYXntIrm1/numKDo113zx1WMOFO69LJ paul"
];
# packages = with pkgs; [];
};
# Users in group wheel may sudo without password
security.sudo.wheelNeedsPassword = false;
# Users in group wheel are special friends of the Nix daemon
nix.settings.trusted-users = [
"@wheel"
];
# List packages installed in system profile. To search, run:
# $ nix search wget
environment.systemPackages = with pkgs; [
vim
tmux
bottom
(pkgs.callPackage ../packages/ionos-dyndns.nix {})
];
# List services that you want to enable:
# Enable the OpenSSH daemon.
services.openssh = {
enable = true;
settings = {
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
};
};
# Enable Avahi for mDNS (advertise hostname in LAN)
services.avahi = {
enable = true;
nssmdns = true;
};
services.spigot-server = {
enable = true;
user = "spigot";
};
# Secrets management
age.secrets = {
ionos-prefix = {
file = ../secrets/ionos-prefix.age;
owner = "ionos-dyndns";
group = "ionos-dyndns";
};
ionos-secret = {
file = ../secrets/ionos-secret.age;
owner = "ionos-dyndns";
group = "ionos-dyndns";
};
};
# DynDNS stuff. IONOS has a (proprietary?) API for this,
# so we're using a Python script from the interwebs :shrug:
services.ionos-dyndns = {
enable = true;
# Must match the user owning the secrets below. See agenix config
# above for more details.
user = "ionos-dyndns";
apiPrefixPath = config.age.secrets.ionos-prefix.path;
apiSecretPath = config.age.secrets.ionos-secret.path;
aaaa = true;
fqdn = "blocks.beany.club";
interface = "enp0s25";
};
# Open ports in the firewall.
networking.firewall.allowedTCPPorts = [ 25565 ];
networking.firewall.allowedUDPPorts = [ 25565 ];
# Or disable the firewall altogether.
# networking.firewall.enable = false;
# TODO: Backups
# Practical hardware options
services.logind.lidSwitch = "ignore";
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
# Copy the NixOS configuration file and link it from the resulting system
# (/run/current-system/configuration.nix). This is useful in case you
# accidentally delete configuration.nix.
# system.copySystemConfiguration = true;
# This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions
# on your system were taken. It's perfectly fine and recommended to leave
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "23.05"; # Did you read the comment?
}

3
nix/gilgamesh/deploy.sh Executable file
View File

@ -0,0 +1,3 @@
#!/usr/bin/env bash
nixos-rebuild -I nixos-config=configuration.nix --target-host gilgamesh --use-remote-sudo switch

View File

@ -0,0 +1,33 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:
{
imports =
[ (modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [ "ehci_pci" "ahci" "usb_storage" "sd_mod" "sdhci_pci" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "/dev/disk/by-label/NIXROOT";
fsType = "ext4";
};
swapDevices = [ ];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.enp0s25.useDHCP = lib.mkDefault true;
# networking.interfaces.wlp3s0.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View File

@ -0,0 +1,118 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.ionos-dyndns;
ionos-dyndns = pkgs.callPackage ../packages/ionos-dyndns.nix {};
command = lib.concatStringsSep " " (
[
"${ionos-dyndns}/bin/ionos-dyndns"
"--api-prefix"
"$(cat ${cfg.apiPrefixPath})"
"--api-secret"
"$(cat ${cfg.apiSecretPath})"
"--fqdn"
cfg.fqdn
"--interface"
cfg.interface
]
++ lib.optionals cfg.a [ "--A" ]
++ lib.optionals cfg.aaaa [ "--AAAA" ]
);
in {
options = {
services.ionos-dyndns = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to turn on the IONOS DynDNS timer.
'';
};
user = mkOption {
type = types.str;
default = "ionos-dyndns";
};
apiPrefixPath = mkOption {
type = types.path;
description = ''
Path of a file holding the API prefix.
'';
};
apiSecretPath = mkOption {
type = types.path;
description = ''
Path of a file holding the API secret.
'';
};
a = mkOption {
type = types.bool;
default = false;
description = ''
Whether to set the A record (IPv4).
'';
};
aaaa = mkOption {
type = types.bool;
default = false;
description = ''
Whether to set the AAAA record (IPv6).
'';
};
fqdn = mkOption {
type = types.str;
description = ''
Fully qualified domain name for this host.
'';
};
interface = mkOption {
type = types.str;
description = ''
Interface to get the IP address from.
'';
};
interval = mkOption {
type = types.str;
default = "14min";
description = "How often to run the update script in systemd.timers notation.";
};
serviceName = mkOption {
type = types.str;
default = "ionos-dyndns";
};
};
};
config = mkIf cfg.enable {
users = {
users = {
${cfg.user} = {
isSystemUser = true;
group = cfg.user;
description = "IONOS DynDNS user.";
};
};
groups = {
${cfg.user} = {
};
};
};
systemd = {
services.${cfg.serviceName} = {
serviceConfig = {
Type = "oneshot";
User = cfg.user;
# We assume that command doesn't contain any single quotes
ExecStart = "${pkgs.bash}/bin/bash -c '${command}'";
};
};
timers.${cfg.serviceName} = {
wantedBy = [ "timers.target" ];
timerConfig = {
Unit = "${cfg.serviceName}.service";
OnBootSec = "30s";
OnActiveSec = cfg.interval;
};
};
};
};
}

View File

@ -0,0 +1,81 @@
{ config, lib, pkgs, ... }:
with lib;
let
spigot-server = pkgs.callPackage ../packages/spigot-server.nix {};
cfg = config.services.spigot-server;
StateDirectory = "spigot-server";
in {
options = {
services.spigot-server = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to turn on the Spigot Minecraft server.
'';
};
user = mkOption {
type = types.str;
default = "spigot-server";
description = ''
The user account and group that Spigot runs as.
'';
};
};
};
config = mkIf cfg.enable {
users.users = {
${cfg.user} = {
isSystemUser = true;
group = cfg.user;
description = "Spigot Minecraft server user";
};
};
users.groups = {
${cfg.user} = {
};
};
systemd = {
services.spigot-server = {
description = "Spigot Minecraft server";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
User = "${cfg.user}";
Sockets = "spigot-server.socket";
StandardInput = "socket";
StandardOutput = "journal";
StandardError = "journal";
inherit StateDirectory;
WorkingDirectory = "/var/lib/${StateDirectory}";
ExecStart = "${spigot-server}/bin/spigot-server -nogui";
ExecStop = [
"${pkgs.bash}/bin/bash -c '${pkgs.coreutils}/bin/echo save-all > /run/spigot-server.stdin'"
"${pkgs.bash}/bin/bash -c '${pkgs.coreutils}/bin/echo stop > /run/spigot-server.stdin'"
# Wait for the main process to exit
# If we don't do this systemd tries to nudge Java to stop, causing a race condition
# that leads to an ungraceful shutdown
"${pkgs.coreutils}/bin/echo \"Waiting for \${MAINPID} to exit...\""
"${pkgs.bash}/bin/bash -c 'while ${pkgs.coreutils}/bin/kill -s 0 $MAINPID 2>/dev/null; do sleep 0.5; done'"
];
};
};
sockets.spigot-server = {
description = "Spigot Minecraft server socket for commands and stuff";
unitConfig = {
# Automatically start and stop socket along with the service
PartOf = "spigot-server.service";
};
socketConfig = {
ListenFIFO = "/run/spigot-server.stdin";
};
};
};
};
}

1
nix/packages/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
spigot-1.20.1.jar

11
nix/packages/README.md Normal file
View File

@ -0,0 +1,11 @@
# Packages
## `spigot-server`
In order to build `spigot-server.nix` you'll need a copy of the Spigot JAR.
For licensing reasons I won't check it into Git.
Just drop `spigot-${version}.jar` into this folder and change the `version = ` line in `spigot-server.nix` accordingly.
## TODO
- Make some more stuff in `spigot-server.nix` configurable

View File

@ -0,0 +1,37 @@
{
fetchFromGitHub,
lib,
makeWrapper,
stdenv,
# Runtime Dependencies
python3,
# grep
gnugrep,
# ip
iproute2,
# hostname
hostname
}:
let
pythonWithDeps = python3.withPackages (p: [p.requests]);
in stdenv.mkDerivation rec {
pname = "ionos-dyndns";
# Packaging time, not commit time
version = "20231118";
src = fetchFromGitHub {
owner = "lazaroblanc";
repo = "IONOS-DynDNS";
rev = "6c090ab928ce8d6eaa28b09614995b036ad60027";
hash = "sha256-rabDuKuPvzcMltnCSvc5kDjcDhv7sXxbDLWw3/hdSmk=";
};
nativeBuildInputs = [ makeWrapper ];
buildCommand = ''
install -Dm755 $src/ionos_dyndns.py $out/lib/ionos_dyndns.py
makeWrapper ${pythonWithDeps}/bin/python3 $out/bin/ionos-dyndns \
--set PATH ${lib.makeBinPath [ iproute2 gnugrep hostname ]} \
--add-flags $out/lib/ionos_dyndns.py
'';
}

View File

@ -0,0 +1,26 @@
{
makeWrapper,
stdenv,
# Runtime Dependencies
jre
}:
let
# Copied from some forum thread without much thought.
# Let's see if they work out.
javaFlags = "-Xmx5G -XX:+UseG1GC -XX:+UnlockExperimentalVMOptions -XX:MaxGCPauseMillis=50 -XX:+DisableExplicitGC -XX:TargetSurvivorRatio=90 -XX:G1NewSizePercent=50 -XX:G1MaxNewSizePercent=80 -XX:InitiatingHeapOccupancyPercent=10 -XX:G1MixedGCLiveThresholdPercent=50";
in stdenv.mkDerivation rec {
pname = "spigot-server";
version = "1.20.1";
src = ./spigot-${version}.jar;
nativeBuildInputs = [ makeWrapper ];
buildCommand = ''
install -Dm644 $src $out/lib/spigot-${version}.jar
makeWrapper ${jre}/bin/java $out/bin/spigot-server \
--argv0 spigot-server \
--add-flags "${javaFlags}" \
--add-flags "-jar $out/lib/spigot-${version}.jar"
'';
}

11
nix/secrets/README.md Normal file
View File

@ -0,0 +1,11 @@
# secrets
> Nix configuration secrets managed with [agenix](https://github.com/ryantm/agenix#tutorial).
Use `nix develop` in the repository root to drop into a shell with `agenix`.
## Editing files
```
agenix -e <thingamajig.age>
```

View File

@ -0,0 +1,9 @@
age-encryption.org/v1
-> ssh-ed25519 9V3MUQ 7+lohnPlQALVPEGo2LwS2fj5r2RCKaVeEFmi6EYEyCE
9U6eAthRVd5ry0ej79FEy3oRG3okJTwY6zSN1u68H1o
-> ssh-ed25519 CcM6/g QQX9SsgKkk8YdUPRKj9Tda8mf6qRJ7ywtP6IIpN9fxo
3Ml2+1+AQMwr5Lnv84pYOee/s5mzfVdsHRLaUIAKNFk
-> i)!b3gaJ-grease 7|bwS ?k2JgF E-G 2HI
0mFbZ22lqvLd
--- 0+CwYGJlJC7bRbokHSlv+V4JKppBo+/ocfjp2NQBD3Q
JDv<04> ë<C2A0>¶ÚŤÄ÷ V/Ă'OM ¸x×é!ȸTÉA7ÍK5#É8©&•Ř-VqČ&}ů]ráÂ

Binary file not shown.

10
nix/secrets/secrets.nix Normal file
View File

@ -0,0 +1,10 @@
let
# Users
paul = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIMFqREiw3EareYXntIrm1/numKDo113zx1WMOFO69LJ";
# Systems
gilgamesh = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPDmLWYK6/4/Fh+wsoiz9+PCHvNcP2/wu2GvfzrqXCGA";
in {
"ionos-prefix.age".publicKeys = [ paul gilgamesh ];
"ionos-secret.age".publicKeys = [ paul gilgamesh ];
}