This commit is contained in:
nora 2025-08-03 00:33:53 +02:00
parent a1187fbef5
commit 68174b4a77
49 changed files with 88 additions and 585 deletions

View file

@ -1,27 +0,0 @@
name: Run playbooks
on:
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
name: Run playbooks
steps:
- uses: actions/checkout@8b5e8b768746b50394015010d25e690bfab9dfbc # v3.6.0
- name: Unlock secrets
uses: sliteteam/github-action-git-crypt-unlock@8b1fa3ccc81e322c5c45fbab261eee46513fd3f8 # v1.2.0
env:
GIT_CRYPT_KEY: ${{ secrets.GIT_CRYPT_KEY_BASE64 }}
- name: Run Ansible playbook
uses: dawidd6/action-ansible-playbook@260ab3adce54d53c5db8f1b2eed1380ae5c73fea # v2.6.1
with:
playbook: all.yml
directory: playbooks
key: ${{ secrets.VPS_DEPLOY_KEY }}
known_hosts: |
vps1.nilstrieb.dev ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOjiNfzZQpN2KWd1LSM/LL+dLx8snlCV6jYys+W4NOBH
vps2.nilstrieb.dev ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKzt3OZAOG2sih8T9Bhoqg8ANBP5ZX60z0xmUW4cBWvX
options: |
--inventory inventory.yml
-u root

View file

@ -7,9 +7,9 @@ APP="$1"
if [ "$APP" = "hugo-chat" ]; then
REPO="https://github.com/C0RR1T/HugoChat.git"
elif [ "$APP" = "cors" ]; then
REPO="https://github.com/nilstrieb-lehre/davinci-cors.git"
REPO="https://github.com/noratrieb-lehre/davinci-cors.git"
else
REPO="https://github.com/Nilstrieb/$APP.git"
REPO="https://github.com/Noratrieb/$APP.git"
fi
echo "Checking out $REPO"

View file

@ -1 +0,0 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC0Yl4+vAFgN+d82emRY8tHDgM7Pp0rLIsKBZku+YUsd vps-deploy-key

View file

@ -5,17 +5,6 @@ New infra based on more servers and more shit.
All servers have their hostname as their name here and are reachable via `$hostname.infra.noratrieb.dev`.
They will have different firewall configurations depending on their roles.
```
-------- --------
| dns1 | | dns2 |
-------- --------
--------
| vps1 |
--------
```
## DNS

View file

@ -53,7 +53,16 @@
wg = {
privateIP = "10.0.0.1";
publicKey = "5tg3w/TiCuCeKIBJCd6lHUeNjGEA76abT1OXnhNVyFQ=";
peers = [ "vps3" "vps4" "vps5" ];
peers = [ "vps2" "vps3" "vps4" "vps5" ];
};
};
vps2 = {
publicIPv4 = "184.174.32.252";
publicIPv6 = null;
wg = {
privateIP = "10.0.0.2";
publicKey = "SficHHJ0ynpZoGah5heBpNKnEVIVrgs72Z5HEKd3jHA=";
peers = [ "vps1" "vps3" "vps4" "vps5" ];
};
};
vps3 = {
@ -62,7 +71,7 @@
wg = {
privateIP = "10.0.0.3";
publicKey = "pdUxG1vhmYraKzIIEFxTRAMhGwGztBL/Ly5icJUV3g0=";
peers = [ "vps1" "vps4" "vps5" "dns1" "dns2" ];
peers = [ "vps1" "vps2" "vps4" "vps5" "dns1" "dns2" ];
};
};
vps4 = {
@ -73,7 +82,7 @@
wg = {
privateIP = "10.0.0.4";
publicKey = "+n2XKKaSFdCanEGRd41cvnuwJ0URY0HsnpBl6ZrSBRs=";
peers = [ "vps1" "vps3" "vps5" ];
peers = [ "vps1" "vps2" "vps3" "vps5" ];
};
};
vps5 = {
@ -82,7 +91,7 @@
wg = {
privateIP = "10.0.0.5";
publicKey = "r1cwt63fcOR+FTqMTUpZdK4/MxpalkDYRHXyy7osWUk=";
peers = [ "vps1" "vps3" "vps4" ];
peers = [ "vps1" "vps2" "vps3" "vps4" ];
};
};
};
@ -190,6 +199,19 @@
deployment.tags = [ "caddy" "eu" "apps" "website" ];
system.stateVersion = "23.11";
};
# VPS2 exists
vps2 = { name, nodes, modulesPath, config, lib, ... }: {
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
./modules/contabo
./modules/wg-mesh
./modules/caddy
./modules/garage
];
deployment.tags = [ "caddy" "eu" "apps" ];
system.stateVersion = "23.11";
};
# VPS3 is the primary monitoring/metrics server.
vps3 = { name, nodes, modulesPath, config, ... }: {
imports = [

View file

@ -37,11 +37,6 @@ let
ns1 = dns1;
ns2 = dns2;
# apps
cors-school = vps2 // {
subdomains.api = vps2;
};
localhost.A = [ (a "127.0.0.1") ];
# --- retired:

View file

@ -9,9 +9,6 @@ let
lib.optionalAttrs (publicIPv4 != null) { A = [ (a publicIPv4) ]; } //
lib.optionalAttrs (publicIPv6 != null) { AAAA = [ (aaaa publicIPv6) ]; })
networkingConfig;
vps2 = {
A = [ "184.174.32.252" ];
};
combine = hosts: {
A = lib.lists.flatten (map (host: if builtins.hasAttr "A" host then host.A else [ ]) hosts);
@ -63,9 +60,6 @@ let
};
};
# --- legacy crap
old-docker = vps2;
# --- apps
bisect-rustc = vps1;
docker = vps1;

View file

@ -6,13 +6,6 @@
- co-du -> Contabo Düsseldorf
- he-nu -> Hetzner Nürnberg
| name | disk space | identifier | zone |
| ---- | ---------- | ---------- | ----- |
| vps3 | 70GB | cabe | co-du |
| vps3 | 100GB | 020bd | co-ka |
| vps4 | 30GB | 41e40 | he-nu |
| vps5 | 100GB | 848d8 | co-du |
## buckets
- `caddy-store`: Store for Caddy webservers
@ -35,6 +28,7 @@
- `loki`: `GK84ffae2a0728abff0f96667b`
- `backups`: `GK8cb8454a6f650326562bff2f`
- `forgejo`: `GKc8bfd905eb7f85980ffe84c9`
- `upload-files`: `GK607464882f6e29fb31e0f553`
- `admin`: `GKaead6cf5340e54a4a19d9490`
- RW permissions on ~every bucket

View file

@ -1,5 +1,5 @@
age-encryption.org/v1
-> ssh-ed25519 qM6TYg QziuzHQxmWyRdv8dUPBWTgnMxFtqR6ttP16Z3XdvD3Y
Krxmha5J+gTU0DjzPDTDIwz1mW0Q84XR2FgQyPm4bf4
--- t4Mea1Y35o5t2dhREnp8Zq1AyR4DAWMFW7Vv3CkgGKw
ìlTS+Ƴ6y­¿rîëOØné<6E>&c`Ï°Ê ü<>:û³7V»-tf±puw€I¥w“Âøå
-> ssh-ed25519 qM6TYg UtoSFhZQ2PW1y3ifXgSdQQswoi5kdRg2gvczlEateC4
ir2FpFkYo17MGBy+C4thM4lit7vn2CiBi09DcTb6ubs
--- YvRhsfFzedjeKssmOTzHvKkvIG0zXVVCIJsRNc/LTVg
 €KîÞ$é†Prm;Û·ûÎªæ ¹Œö+é ÚqE@<40>Àv]¢Ôòm =Í™'Sm

View file

@ -1,6 +1,7 @@
age-encryption.org/v1
-> ssh-ed25519 qM6TYg ecu0Ic6o+WyT7XhZPo0Yf46bOye2LAgnJ5MxFPTY/E0
JqJCtQmtxgktMl/4HsHh0uRp/rzEoqT9Z81H9v1RXio
--- /CmBzuDf0AcCk6rAvEh5SmIMxpwCTjfj9IQtRLv5qYA
}Œ=5i
©¨£#ª4bÎpzCaÀjÙnêB†±€ÍN<C38D>%ÚnO Ž³GKÔ´ÖâõƒÏ”ßÁ¼‹Æçé'ÄZ>T“œì<C593>ÙMøô<}//}|uá5œªsö*
-> ssh-ed25519 qM6TYg GNYf0FjEDEqCe09mS9Hl7OIIjvhKTu8urwUPtY+yyB0
xmAtm4n3s0rfq3S5OKFEG2k/noXFTKMt8hiW5QrD9SU
--- HGBYxXQGM254m2YP5twgjgDme80f0uOL2m4uKy19ZBs
ÖÂ(
Õ×åÇÄT
‚®à±Öì{ÙõF“ü-\ƒ6{mítÏæÊMÑ-óX{‡%bQd]E³Éàü]i¸úãË}F»2¸$7¤ö#k4“;8ZžGþ_oÛ –¼

View file

@ -1,12 +1,13 @@
age-encryption.org/v1
-> ssh-ed25519 qM6TYg B17o68OCsoljQLd4yLx1gZbt9zsFhQE8/QJeZ3Gx+AI
ADxN8iqNN5ApzHMtIXMnMTN4qe/7ba+ZoqkpHDpq9dE
-> ssh-ed25519 XzACZQ Jp5WvbUVmfecvN95vM6+DQmJicVf4u94Vm0mYtBVODw
XAdVpk6bAwAU7OQxvedepr3g8HQo5sY5efy3lYhf1xA
-> ssh-ed25519 51bcvA DUkgjLS805iAsnaCl3B8BOP6cdKOJCx0aK23UEDmTyw
dUZhXJiYkCZvassxSg0Cgf9c+ta2Oc2PNhLdvHBP24M
-> ssh-ed25519 vT7ExA 0Z2/GFY2aqO2HJJet3CRSh3yxchGt7AYTzkl0D2aoEQ
GuMqW7tbsEl/SskgN1hPa0B/aWtet/+pHxmbwsTzPCM
--- vgf72fLRkTVRtJoxh+qfim9YYELE0W74L6ZVjpo+8vI
åø=ê&óŸC»íÄŸŸ#À¥ÑÒ/nܤè´2Â9†ØÞøo[<5B>S+ uWʶ¢£4êÕf/hAÈþ#ïþOs_†RV£òEÆÆóÎûúÎVAlžTÏ/¤VΨtµøJNöËUë;ññnGúQïìÝ£ÖO{Áx[ ¿†íÏP¨Hß9P®:z
ê‰û²åyX„Ñ`]%>¨+ÙÞ~)Ø`VïâxÛ°€i-ƒã¬Fýªš$xHå)ÒTMcZ
-> ssh-ed25519 qM6TYg F9aj1EmsmRSXt1m3a41zpuwFmDBOuuaIrHkqP7PTVno
tVs8Oxa9gV/HdUf0hN/JLuWhbrXI9BXIrsh5HnsKBQI
-> ssh-ed25519 pP9cdg dQdPm3OfbWl5Y8kJxmsUZ4rwpUo8w3+P3CHCiXw9VCw
9yWbGgzgBz9GICAgYiOyPtMjDk/tBb4vsOveTuYP9bw
-> ssh-ed25519 XzACZQ 4lldtotM16DN/75dRX3QEmOzfIEySHcNOlFWqymI+Rs
oOaD7dZu0xC0R7CrVpfwoBU7eSgaWyJmAZ4WptCQdes
-> ssh-ed25519 51bcvA k9eq2Tc3A9MztsdTvt3sDYUj/usYBJMp9IJQZAR67Ac
ezccfIhPZaHKsVcUrxJL7u3jSA/kCTqLmWuQfxrFQBo
-> ssh-ed25519 vT7ExA BOCylq1RqaburnXxfsl3xqAmGSJnIxVhXK8H2xeFynk
OWhqsbJgHWlo3hsRZVQgEaArK32OI25N4Poi2qJ9wQs
--- bBQkNfDI0onJOyxOJIN3Yl2jkK5iRgYbK67RWsipXOE
3‡ýåA9â¯ÒAÕînÛ¯t•y®ßÚCj-îž{ÏŇâ)ô6¬DfØOÆQ¹Ü}'_n†øÈã‡>UPêNæDRŸÀÁª¨ûÊÆþ-<2D>¾„…éÂ"‡´úÛâšÙ?À>)E0<7F>‡v(~7 C¾O\UJJüŽ$SÂ8èá`€F«˜ÄíšQ§0uÙ3õmH•Ž~P÷Ž£ŒÅLqfõ~ºi¸Æn]=rSre#²wGŒ ³¥@ß|X#éØ÷’Â

Binary file not shown.

Binary file not shown.

View file

@ -2,6 +2,7 @@ let
dns1 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINBKoyDczFntyQyWj47Z8JeewKcCobksd415WM1W56eS";
dns2 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINZ1yLdDhI2Vou/9qrPIUP8RU8Sg0WxLI2njtP5hkdL7";
vps1 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII4Xj3TsDPStoHquTfOlyxShbA/kgMfQskKN8jpfiY4R";
vps2 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKzt3OZAOG2sih8T9Bhoqg8ANBP5ZX60z0xmUW4cBWvX";
vps3 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHvupo7d9YMZw56qhjB+tZPijxiG1dKChLpkOWZN0Y7C";
vps4 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMpoLgBTWj1BcNxXVdM26jDBZl+BCtUTj20Wv4sZdCHz";
vps5 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBWbIznvWQSqRF1E9Gv9y7JXMy3LZxMAWj6K0Nq91kyZ";
@ -13,20 +14,21 @@ in
"hugochat_db_password.age".publicKeys = [ vps1 ];
"openolat_db_password.age".publicKeys = [ vps1 ];
"minio_env_file.age".publicKeys = [ vps1 vps3 ];
"garage_secrets.age".publicKeys = [ vps1 vps3 vps4 vps5 ];
"caddy_s3_key_secret.age".publicKeys = [ vps1 vps3 vps4 vps5 ];
"garage_secrets.age".publicKeys = [ vps1 vps2 vps3 vps4 vps5 ];
"caddy_s3_key_secret.age".publicKeys = [ vps1 vps2 vps3 vps4 vps5 ];
"registry_htpasswd.age".publicKeys = [ vps1 ];
"registry_s3_key_secret.age".publicKeys = [ vps1 ];
"grafana_admin_password.age".publicKeys = [ vps3 ];
"loki_env.age".publicKeys = [ vps3 ];
"backup_s3_secret.age".publicKeys = [ vps1 vps3 vps4 vps5 ];
"s3_mc_admin_client.age".publicKeys = [ vps1 vps3 vps4 vps5 ];
"backup_s3_secret.age".publicKeys = [ vps1 vps2 vps3 vps4 vps5 ];
"s3_mc_admin_client.age".publicKeys = [ vps1 vps2 vps3 vps4 vps5 ];
"killua_env.age".publicKeys = [ vps1 ];
"forgejo_s3_key_secret.age".publicKeys = [ vps1 ];
"upload_files_s3_secret.age".publicKeys = [ vps1 ];
"wg_private_dns1.age".publicKeys = [ dns1 ];
"wg_private_dns2.age".publicKeys = [ dns2 ];
"wg_private_vps1.age".publicKeys = [ vps1 ];
"wg_private_vps2.age".publicKeys = [ vps2 ];
"wg_private_vps3.age".publicKeys = [ vps3 ];
"wg_private_vps4.age".publicKeys = [ vps4 ];
"wg_private_vps5.age".publicKeys = [ vps5 ];

View file

@ -1,6 +1,5 @@
age-encryption.org/v1
-> ssh-ed25519 LZU5Eg dlH/b9FXAowA5m9KYdF+MirRu9fKXhf76jHXuKA6OAI
ADHjmdwYkyd24vbi2jbeI9GmFZuf86/Twm48J3g958s
--- WVLjItfhBqlv55yTzq0/OzfTSfD1ypQfu9EGFf1vUUE
ś‚Ě<ń{©\VLv
Î+Ôv_Ź#PI§¬ăF%(ă„ ¶˛ö>µëôăČźC'nË ő1|jNťüŹŇÔT^6ÇoĹâ
-> ssh-ed25519 LZU5Eg C3IfbvL4t0pOHEb3Bc54+r6DZESgN6K6zPDhBlDumXk
UwOtrqp8I90Vux6L7CsV5K+2SDFB8LBiyLO8ud7IsQU
--- 2tIecoG70broXFTtgjCUMcvk2RdKqpe5tihO6meI8DY
泓、kユレウ& ミ`!ヘ藪_致`<60>マ-。ヤEp^<5E>ザ#:ゥ壌]ム優mサヒy<EFBE8B>厥^O†+t8ァ€<EFBDA7>.コ鉷奘; ョ

View file

@ -1,5 +1,6 @@
age-encryption.org/v1
-> ssh-ed25519 5bWSnQ Li1ITKUHcUQFJX0NQCaz9Abjf6NjyVGTwE9WAzjJAU0
UekGYi4xmM88U0BX52iKGWnBTWCGrxMyMeN6zed12D4
--- MUD9AikW/zNM+W3GiR23pw95ZsDhsxZVn5EMqr0X+DU
Ê‚ý×]?@¥êTHôÀ]~œ?7qéãýŒÍ"W…+`·Ñ<1A>¥+Lµ]ö­‚»Êaœ­ÎSx*¥¹]6Љf¹îÀ
-> ssh-ed25519 5bWSnQ wqkRMdob+7G2mTNKySF2kiGhOKt4GLN/ne+4lM3pIwA
Iz2Brik6I6YHjVxQcoDL0UTJOWcjuiErf5kCeWpnaV0
--- 1ZkP0GiP78eGKl8te1w+o5I5kEbyPaiJFq7WGH4k1LE
á61zIìTÂU/ò5ã'|Œ½ûÊÌþìhÕ>z±ñ¶Ýr^Éwanog´lùX„º,kܶG
cÊõ¸æPÇ!Rh×»fW¥éhä §

View file

@ -0,0 +1,5 @@
age-encryption.org/v1
-> ssh-ed25519 pP9cdg GI2CXAYTJWUqmab/Fnl/cFZVCCBxYZX/snQ+w0aPjSk
8D6TxN4VYH14GQJ/XhUqyfKNLjM8f3LDmykLAvtl+IM
--- 6ru8v60LKlJjpy2PnmcwBdV09KMEh+neITYyuFscSIQ
F Й¿y#<ﯗÖmàߘžº¦¼Q2Õ^T2Lâ9µ]LÄžµhž[b¼rߤ!ï³jEnS?¾ìjCRà%„ÓsŸ;mœƒ\R

View file

@ -1,5 +1,5 @@
age-encryption.org/v1
-> ssh-ed25519 XzACZQ J67LUjHa64q/z1K8zZpx1rsnoQ94NzhkeXEpfNr4ZVQ
dy5Tre9IicxhLBHoqvQAZepG7bNg2dEXFT5iPRcWOcA
--- 9dJKhJeue6VNi0Sw05BX/t8jsxXyRIKz0K3/sy0kT7w
Ýh9ÎÛËi£·ÀÍs¡ØâM =TnÕw€W)<29>õ€Ûòêã²îÃ\ÇÕ<2*%æ_ëå×ܳ¿«ôgÇLñõN5c—D5ô@áÍ»ÂØ
-> ssh-ed25519 XzACZQ pOD3jNWIufLkEVtkFJu6W0QjdzPJTK+t1MwgACv1zXU
EJQ+9xPw6MnB6nJW6nDBUlzfHyY9XlfBIQlgje+FVE4
--- BmTwJED+mJ/Qr0WFDELozwR2BgGDkHDcR2I9eSxuVn8
KêÃ~alNh.€½ù «kiAÛF*Ã/MY±ñ¡Zd†¬p”AÉ+-²Ù¬A<C2AC>¹Ü¢*S¥Z¶ï„ Nê­F­fˆbô3tª×rûÇy

View file

@ -1,5 +1,6 @@
age-encryption.org/v1
-> ssh-ed25519 51bcvA P7ouUh98Mfi9Jsu6MDWaWH0NB2alXRIK8hxBIs0Nylg
tUZ1sWLlvPizsSWhK3fnVVhr4C9Ign5rwowxePGXFII
--- PHPizXT8GPP9mIFg1paqqc8w3qsX63XpLkeT0APybik
´B§?*8-nËLsÍj< k*.@¯ªœé6K‡Ug ×'8¼ Ñ#Žòíhç.l~Sà3£%¶šÀ!ŸVYK•l¿R¾ ´Ôؘo
-> ssh-ed25519 51bcvA mzB9FcwUgPczK4/Rd2DZvCYoQfjT4qE+Z7HE9yHjgGU
sPDlr+YNhvbjYagyJb/kua9dWeG9tSt6KNjKh+/p+ps
--- uZVoWpqKjapTtWRGpc7cUoifwOVFfd5DU+9pQpwruuo
Fv6¾œÚËï,ø»K¶¶Ó†(ÍÝèkÙ~Y4Á.`z(]w2²MV "¼%À³JUÚ$ô•È«ÁǸCïG
_:F¸Ý§ S

View file

@ -1,5 +1,5 @@
age-encryption.org/v1
-> ssh-ed25519 vT7ExA 9+j3VYkFAW1obbLc31nv+45SyPMqH1zZPkI+PU4lVH8
G9QkkyTNH499EWhjiXCyXt7HgHlzJTZsaLiR+yOF18E
--- vq7bT3yTioJ1UsD7hSu5jyYKhOE6UMIMsosu4f5pK1w
Q±<>žž¹ýÁ˜ÅVÐé#<23>(7èýÎEYÉÛÅÌ\ú££Z¨?GÙ«ç_C ÛI¦î ЉgNi´V¯åe]•¢tx@¸w+
-> ssh-ed25519 vT7ExA WsT1cFerSGwOnhrLBTN62zydQVC1oPQxXtwQxGUSY1w
Je1zd3NJ16yaOHQD8iPX7eaPJV3WH6Z3eiDkFip/2FY
--- J6ZhIFcXF12n+pV4JEaAut/QB2c5ycYSIGo6j3nLICQ
SńOĆŤ<EFBFBD>žsIµ˝öüÜLJăŢ i—=Ům|,gőnYÖDv·ćA âd{Á·á q)~Ă3Ó!ó8¶ ·«ŢěńxPçÚńL7™"

View file

@ -1,5 +1,5 @@
age-encryption.org/v1
-> ssh-ed25519 qM6TYg sAwuep3NgetXEKK5N8ZFP6Y0IDAGtTLIXH1hh5L0Hyc
8pB7uytmRSkJMKi5S9YSLHKLgpYKkv5w2WaKaJL9sT4
--- JucAnOMMuFLpIyg9t+Azths9ttk6by6SKcMWA6Cwa+0
v§õÐ(TR͘ä´<C3A4>JpÂDòÀ%J—*^îl—ß±½ÂY…/‰§ê'®zBÙž˜Áë÷4§±GÛ6Æ·(å‹ /\,Wérææ7 ééeón€%á²@<40>
-> ssh-ed25519 qM6TYg n/6/3HfVk0IWfGRbgBB7qLkEXylLgYDxNzbLTaJWyhs
jNP6viJqbOgpNke072hDeaGmApVc51wAN/O+8Gc58U4
--- WoF4XMNOMMwKJ16Q7QrH97cGdyJ4nB4Dw04dyznfmL8
þÿ#ÙÖõ"ØLËÆi"W€µ<E282AC><>AEŒèû-?Ø•´ìæ´~Z¿\±éÞðgO¨&Ùõ¥´õÊx¤»³vÈç —¼þ¹¢&w]ý"¢¿S2VɯÁ/”É

Binary file not shown.

View file

@ -1,5 +0,0 @@
---
- name: Generic setup
ansible.builtin.import_playbook: ./basic-setup.yml
- name: VPS 2
ansible.builtin.import_playbook: ./vps2.yml

View file

@ -1,112 +0,0 @@
---
- name: Basic Server setup
hosts: all
gather_facts: false
tasks:
- name: Change hostname
ansible.builtin.hostname:
name: "{{ inventory_hostname }}"
- name: apt update
ansible.builtin.apt:
update_cache: true
upgrade: yes
- name: Install fish
ansible.builtin.apt:
name: "fish"
state: present
- name: "Change root's shell to fish"
ansible.builtin.user:
name: root
shell: /usr/bin/fish
- name: Install useful tools
ansible.builtin.apt:
name: "{{ item }}"
state: present
with_items:
- htop
- awscli
- name: Install keyring packages
ansible.builtin.apt:
name: "{{ item }}"
with_items:
- debian-keyring
- debian-archive-keyring
- apt-transport-https
- name: Add caddy keyrings
ansible.builtin.shell: |
set -euo pipefail
rm -f /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
# todo: show ok/changed
args:
executable: /bin/bash
- name: Add caddy repository
ansible.builtin.get_url:
url: "https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt"
dest: "/etc/apt/sources.list.d/caddy-stable.list"
mode: "u=rw,g=r,o=r"
- name: Add the docker GPG key
ansible.builtin.get_url:
url: "https://download.docker.com/linux/ubuntu/gpg"
dest: "/etc/apt/keyrings/docker.asc"
mode: "u=r,g=r,o=r"
- name: Add docker repository
ansible.builtin.copy:
dest: "/etc/apt/sources.list.d/docker.list"
content: "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu jammy stable"
- name: Install docker
ansible.builtin.apt:
name: "{{ item }}"
state: present
with_items:
- docker-ce
- docker-ce-cli
- docker-compose-plugin
- name: Ensure docker is started
ansible.builtin.service:
name: docker
state: started
- name: Install caddy
ansible.builtin.apt:
name: caddy
state: present
args:
update_cache: true
- name: Ensure caddy is started
ansible.builtin.service:
name: caddy
state: started
- name: Create debug html root
ansible.builtin.file:
path: /var/www/html/debug
state: directory
mode: "u=rwx,g=rx,o=rx"
- name: Create debug webserver file
ansible.builtin.copy:
dest: /var/www/html/debug/index.html
src: "../debug.html"
mode: "u=rw,g=r,o=r"
- name: Copy Caddyfile
ansible.builtin.copy:
dest: /etc/caddy/Caddyfile
src: "../{{ inventory_hostname }}/Caddyfile" # TODO: Choose the right caddyfile depending on the server.
mode: "u=rw,g=r,o=r"
notify:
- "Caddyfile changed"
- name: Create /apps
ansible.builtin.file:
path: /apps
state: directory
mode: u=rwx,g=rx,o=rx
- name: Copy docker-compose
ansible.builtin.copy:
dest: /apps/docker-compose.yml
src: "../{{ inventory_hostname }}/docker-compose.yml" # TODO: choose the right directory
mode: "u=r,g=r,o=r"
handlers:
- name: "Caddyfile changed"
ansible.builtin.service:
name: caddy
state: reloaded

View file

@ -1,4 +0,0 @@
vps:
hosts:
vps2:
ansible_host: vps2.noratrieb.dev

View file

@ -1,97 +0,0 @@
---
- name: VPS 2 setup
hosts: vps2
gather_facts: false
tasks:
- name: Copy backup file
ansible.builtin.copy:
src: "../vps2/backup.sh"
dest: "/apps/backup.sh"
mode: "u=rx,g=rx,o=rx"
- name: Configure backup cron
ansible.builtin.cron:
name: Daily backup
minute: "5"
hour: "7"
job: "/apps/backup.sh"
#####
# APP: karin bot, /apps/karin-bot
#####
- name: Create /apps/karin-bot
ansible.builtin.file:
path: /apps/karin-bot
state: directory
mode: "u=rwx,g=rx,o=rx"
- name: "Copy karin .env secret"
ansible.builtin.copy:
dest: "/apps/karin-bot/.env"
src: "../secrets/karin-bot/.env"
mode: "u=r,g=r,o=r"
# TODO: Mount a volume in the karin-db to this directory
#####
# APP: cors-school, /apps/cors-school
#####
- name: Create /apps/cors-school
ansible.builtin.file:
path: /apps/cors-school
state: directory
mode: "u=rwx,g=rx,o=rx"
- name: Copy secret envs
ansible.builtin.copy:
dest: "/apps/cors-school/{{ item }}"
src: "../secrets/cors-school/{{ item }}"
mode: "u=r,g=r,o=r"
with_items:
- bot.env
- db.env
- server.env
#####
# APP: minecraft server, /apps/minecraft
#####
- name: Create /apps/minecraft
ansible.builtin.file:
path: /apps/minecraft
state: directory
mode: "u=rwx,g=rx,o=rx"
- name: Copy minecraft secrets
ansible.builtin.copy:
dest: "/apps/minecraft/.env"
src: "../secrets/minecraft/.env"
mode: "u=r,g=r,o=r"
#####
# APP: openolat, /apps/openolat
#####
- name: Create /apps/openolat
ansible.builtin.file:
path: /apps/openolat
state: directory
mode: "u=rwx,g=rx,o=rx"
- name: Copy extra properties
ansible.builtin.copy:
dest: /apps/openolat/extra-properties.properties
src: ../apps/openolat/extra-properties.properties
mode: "u=r,g=r,o=r"
- name: Olat data file permissions # TODO: a bit hacky.
ansible.builtin.file:
path: /apps/openolat/olatdata
state: directory
mode: "u=rwx,g=rwx,o=rwx"
#####
# END: docker compose up!
#####
# We want this to be last so that all app-specific config has been done.
- name: Copy .env
ansible.builtin.copy:
dest: "/apps/.env"
src: "../secrets/vps2.env"
mode: "u=r,g=r,o=r"
- name: Docker compose up! 🚀
community.docker.docker_compose_v2:
project_src: /apps
state: "present"
#####
# POST: things after starting up
#####
- name: Run CORS db migrations
ansible.builtin.shell: |
docker exec -w /app/server cors-school-server diesel migration run

View file

@ -1,23 +0,0 @@
#!/usr/bin/env bash
# Copies a base64 encoded deploy key to the servers.
set -eu
printf "Enter private key (base64 encoded): "
read -r key64
private=$(echo "$key64" | base64 -d)
public=$(ssh-keygen -f <(echo "$private") -y)
tmp=$(mktemp -d)
echo "$private" > "$tmp/id"
echo "$public" > "$tmp/id.pub"
delete() {
rm -r "$tmp"
}
trap delete EXIT
ssh-copy-id -i "$tmp/id" root@vps1.nilstrieb.dev
ssh-copy-id -i "$tmp/id" root@vps2.nilstrieb.dev

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,47 +0,0 @@
{
email nilstrieb@gmail.com
}
# https://gist.github.com/ryanburnette/d13575c9ced201e73f8169d3a793c1a3
(cors) {
@cors_preflight{args.0} method OPTIONS
@cors{args.0} header Origin {args.0}
handle @cors_preflight{args.0} {
header {
Access-Control-Allow-Origin "{args.0}"
Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE, OPTIONS"
Access-Control-Allow-Credentials "false"
Access-Control-Allow-Headers "${args.1}"
Access-Control-Max-Age "86400"
defer
}
respond "" 204
}
handle @cors{args.0} {
header {
Access-Control-Allow-Origin "{args.0}"
Access-Control-Expose-Headers *
defer
}
}
}
vps2.nilstrieb.dev {
root * /var/www/html/debug
file_server
}
old-docker.noratrieb.dev {
reverse_proxy * localhost:5000
}
api.cors-school.nilstrieb.dev {
import cors https://cors-school.nilstrieb.dev "DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,token,refresh-token,Authorization"
reverse_proxy * localhost:5003
}
cors-school.nilstrieb.dev {
reverse_proxy * localhost:5004
}

View file

@ -1,76 +0,0 @@
#!/usr/bin/env bash
set -euxo pipefail
BUCKET=nilstrieb-backups
PREFIX="1/$(date --rfc-3339 seconds --utc)"
cd /apps
function upload_file {
local file="$1"
local tmppath
tmppath="$(mktemp)"
cp "$file" "$tmppath"
xz "$tmppath"
aws s3api put-object --bucket "$BUCKET" --key "${PREFIX}/${file}.xz" --body "${tmppath}.xz"
rm "$tmppath.xz"
}
function upload_pg_dump {
local appname="$1"
local containername="$2"
local dbname="$3"
local username="$4"
local tmppath
tmppath="$(mktemp)"
docker exec "$containername" pg_dump --format=custom --file /tmp/db.bak --host "127.0.0.1" --dbname "$dbname" --username "$username"
docker cp "$containername:/tmp/db.bak" "$tmppath"
xz "$tmppath"
aws s3api put-object --bucket "$BUCKET" --key "${PREFIX}/$appname/postgres.bak.xz" --body "$tmppath.xz"
docker exec "$containername" rm "/tmp/db.bak"
rm "$tmppath.xz"
}
function upload_dump_mongo {
local appname="$1"
local containername="$2"
local usernamepassword="$3"
local tmppath
tmppath="$(mktemp)"
docker exec "$containername" mongodump --archive=/tmp/db.bak --uri="mongodb://${usernamepassword}@127.0.0.1:27017"
docker cp "$containername:/tmp/db.bak" "$tmppath"
xz "$tmppath"
aws s3api put-object --bucket "$BUCKET" --key "${PREFIX}/$appname/db.bak.xz" --body "$tmppath.xz"
docker exec "$containername" rm "/tmp/db.bak"
rm "$tmppath.xz"
}
function upload_directory {
local appname="$1"
local directory="$2"
local filename="$3"
local tmppath
tmppath="$(mktemp)"
tar -cJf "$tmppath" "$directory"
aws s3api put-object --bucket "$BUCKET" --key "${PREFIX}/$appname/$filename" --body "$tmppath"
rm "$tmppath"
}
upload_pg_dump "cors-school" "cors-school-db" "davinci" "postgres"
# shellcheck disable=SC1091
source "karin-bot/.env"
upload_dump_mongo "karin-bot" "karin-bot-db" "$MONGO_INITDB_ROOT_USERNAME:$MONGO_INITDB_ROOT_PASSWORD"
upload_directory "openolat" "openolat/olatdata" "olatdata.tar.xz"
echo "Finished backup!"

View file

@ -1,109 +0,0 @@
version: "3.8"
services:
#### Karin
karin_bot_db:
container_name: karin-bot-db
image: "mongo:latest"
restart: always
volumes:
- "/apps/karin-bot/data:/data/db"
environment:
RUST_LOG: info
PRETTY: "true"
env_file:
- "/apps/karin-bot/.env"
networks:
- karin-bot
deploy:
resources:
limits:
cpus: "0.5"
memory: 500M
karin_bot:
container_name: karin-bot
image: "docker.noratrieb.dev/discord-court-bot:921be642"
restart: always
env_file:
- "/apps/karin-bot/.env"
environment:
DB_NAME: court_bot
MONGO_URI: "mongodb://karin-bot-db:27017"
RUST_LOG: INFO
PRETTY: "false"
networks:
- karin-bot
#### Cors School
cors_school_db:
container_name: cors-school-db
image: "postgres:latest"
restart: always
volumes:
- "/apps/cors-school/data:/var/lib/postgresql/data"
env_file:
# POSTGRES_PASSWORD=PASSWORD
- "/apps/cors-school/db.env"
environment:
POSTGRES_DB: davinci
PGDATA: "/var/lib/postgresql/data/pgdata"
networks:
- cors-school
cors_school_server:
container_name: cors-school-server
image: "docker.noratrieb.dev/cors-school-server:bef75a80"
restart: always
env_file:
# DATABASE_URL=postgres://postgres:PASSWORD@cors-school-db/davinci
# JWT_SECRET=secret
- "/apps/cors-school/server.env"
environment:
RUST_LOG: info
networks:
- cors-school
ports:
- "5003:8080"
cors_school_client:
container_name: cors-school-client
image: "docker.noratrieb.dev/cors-school-client:bef75a80"
restart: always
ports:
- "5004:80"
cors_school_bot:
container_name: cors-school-bot
image: "docker.noratrieb.dev/cors-school-bot:bef75a80"
restart: always
volumes:
# DISCORD_TOKEN=
# CORS_API_TOKEN=
- "/apps/cors-school/bot.env:/.env"
environment:
APPLICATION_ID: "867725027080142870"
RUST_LOG: info
BACKEND_URL: "http://cors-school-server:8080/api"
networks:
- cors-school
# minecraft_server:
# container_name: minecraft-server
# image: itzg/minecraft-server:latest
# restart: always
# environment:
# - TYPE=VANILLA
# - VERSION=1.20.1
# - DIFFICULTY=HARD
# - EULA=TRUE
# - MOTD=baden
# - MEMORY=6G
# - MODE=creative
# - PVP=true
# - SERVER_NAME=hallenbad
# - USE_AIKAR_FLAGS=true
# env_file:
# # For example, storing the WHITELIST and OPS
# - /apps/minecraft/.env
# ports:
# - "25565:25565"
# volumes:
# - /apps/minecraft/server:/data
networks:
cors-school:
karin-bot: