diff --git a/.ansible-lint b/.ansible-lint index e750c57..8264714 100644 --- a/.ansible-lint +++ b/.ansible-lint @@ -1,6 +1,7 @@ skip_list: - "yaml[line-length]" - "name[casing]" + - "yaml[brackets]" exclude_paths: - .forgejo/ diff --git a/inventories/z9/host_vars/rt1.sops.yaml b/inventories/z9/host_vars/rt1.sops.yaml new file mode 100644 index 0000000..f4141fd --- /dev/null +++ b/inventories/z9/host_vars/rt1.sops.yaml @@ -0,0 +1,198 @@ +secrets__secrets: + - name: ENC[AES256_GCM,data:MmqDXUKy+U67JZFmKJTGLYAJcYPClQ8M2w==,iv:/eDx++bJCzdKXYB8YipB/GB6aM421JR3sy8i5trBKxk=,tag:/zTklys9bN839iT1qOH0UQ==,type:str] + content: ENC[AES256_GCM,data:2ljp324rAsF2zk2631TI7bV1xKxdFr4u4NxrsPYnjWsL0PX0n0KhJ1qvJCs=,iv:0+DxsTTiNLOg5iH83bFT/d+0uW2rn6bATSm3xc5PEdE=,tag:XbBDrrjriXPedyT4+sBBwA==,type:str] + - name: ENC[AES256_GCM,data:9i4hZU7Hv/IMlI/1oYthx8g57nrst9LHZQk=,iv:IQanD/CA64A+hVyTQBiTvWdXyY8qNF9BpehWZxI5a9c=,tag:RiY0OJe2xbFPG6wfe5XjiA==,type:str] + content: ENC[AES256_GCM,data:lrwHaNvHkh5E94ziiQsd8ua9YvuwmhZ6iIGZS0oFnZdYKuyNh7egWOoii2o=,iv:LLRKhbiJl1GwK/SfqNdNrrJuDF17YXw3hHmuhlyI87w=,tag:DbR/a7jfy1+4yswSdYfOFA==,type:str] + - name: ENC[AES256_GCM,data:2lJUcDJ7ECJ1bF4Fg1VwOR2tBIQ77ZvDAbFF8w==,iv:HrPWIetjN/lOyQ7Mvk0sM1w+bWldlNfWhvw7/sfqKN8=,tag:AJL0s+f0O/yR4G3RVd1IHQ==,type:str] + content: ENC[AES256_GCM,data:68GUwG1Q2s2jH92HS0FQWrcMHJP8fHjrOqr21gsdswxKekQrpxX5B3BBFfM=,iv:HOsNUAKE5rOmKgZft2JK1NnZUuhk261d9WYWJS22nLM=,tag:3husFvB57AGVFzF7hKzLpw==,type:str] + - name: ENC[AES256_GCM,data:ESxpEp9k9BdD1GJv+af+U3ny0+RPuaJjWDhQ,iv:DxsZLiDF8F+ixepbUdlitMJ7DLHjGNFNuxRwLl7efo8=,tag:STnv/oLzbchdiwXfKP3fow==,type:str] + content: ENC[AES256_GCM,data:W2h5AcoT85OkekPeRkrf1m0bDdBjG/YNSbWlrcZtP7FjaPh/F+cx+J6oRRI=,iv:CLVXTqfstpIU3BX/Zdcnp9w0gWxeGDI/G1MNl6xr4ZU=,tag:yCqN4r1MV/VTWQvZ6COfIw==,type:str] + - name: ENC[AES256_GCM,data:IRwwy+WQxgQ8cDpB8HaCLpKwJj7oC87p0XOxWRo=,iv:BLXNMcigvaOeY6y4NlLPMMWQt9XFi6nodRwIYFgAAnU=,tag:OdQalmujOgrzW8oi64xMRg==,type:str] + content: ENC[AES256_GCM,data:C5oIcuEYtODsvjQZnbqbWVfP63mQzcRuh8f5rlBCyjwSq2mZiYGQe9t0T78=,iv:sITUDo9SKZTSwPfsMv4m4U0ruuVCcaxu7SUT52U4FSE=,tag:4CsSMJWQQPAIeK8DwUDBqg==,type:str] + - name: ENC[AES256_GCM,data:r0sbpjaGjezoNlyl1khy+Dly+8xbbfQZNB8om/E4/tj9lmM=,iv:MLrglBJA6BrHGmFRprlQcf5/Hqh952e5OyQQ9nPxumY=,tag:Se05kMBkSQ7TRxzij7Fo8A==,type:str] + content: ENC[AES256_GCM,data:/c1nRf1eZhbUmoQWvcj8yDaVPtyAN7Uu+S054q3C1/kXlQ7CgOe4CrMXnmk=,iv:ppar0aCKuIU3DOjwAoliZ5TOL199Z+Ffo4pCktjs0W8=,tag:nfaGutK+5KnlWBKU1MTxkQ==,type:str] + - name: ENC[AES256_GCM,data:7mwuykEqbGISOa2n+pWb6INLsHYdjyf2HxTtWpAr5xP1,iv:NMcg+L2DFtBO1nhyPid31yzLr+ZX7DUGl/WxV1MnrqU=,tag:65/BiUEI8v5oMlQqpKNDRg==,type:str] + content: ENC[AES256_GCM,data:SObbA3D/sGN5/i5ps4Zz3alygIXKbSgptFjfPHlwC8G588O+gKAkvKQwU/s=,iv:PY2vLfI3gInFeQbse49KC2/zZ9O4jeXAQ0fpP84GHHE=,tag:214Mb8hIYDkQ4+UkRWtc9w==,type:str] + - name: ENC[AES256_GCM,data:bES9O6JI4wTnuZsup9gflfaozeUDkfjVGNIFn8RnZQ==,iv:98kigM3KZIN5qXNdgfLg5WLmxzAsYCjNqVzyUPco/BI=,tag:1fwEtwQ6i9QQC3OCewN0eA==,type:str] + content: ENC[AES256_GCM,data:flO3Nb4u2WfWNVhn8k5Bgo3LmsHo2cVnLCsrz8ST9Ip7gO9FY9d27FQgphM=,iv:aiDoq+41cSjwcCZRaIPLtbltkOpc7FeuNN7swPqkHXQ=,tag:OhzcY2xKKJF2jZVRseXCFg==,type:str] + - name: ENC[AES256_GCM,data:ERsggezMBbs1YwbIgwzKSAEHWWOWYxap8IDdn2YtEKvZexqu,iv:XbObLp2QERgt57tc/Cpha1CWXi+GttcIU8hJFGSp8e8=,tag:FqCuSbvLRERpVnQTzQsfpQ==,type:str] + content: ENC[AES256_GCM,data:QPoZA71CwE8EFE0I+6z0z0O1bUCMQDDDG7wGNoxXKt3ovLkFt21r8WG7VhA=,iv:InX6A71f3DGTg1wO4G0ECf488+FnKgTHffVwvJ9hHQ0=,tag:EVxwJlneN1CbMLXto7uLFw==,type:str] +sops: + lastmodified: "2026-05-23T21:19:38Z" + mac: ENC[AES256_GCM,data:Ded0VfGn8H2qGMk5LDyqF1gW8hajKc9FgvCynHPQkWkhMSdaHYbFwf//gWi2TjIO22HD5sPw1w9KAjPy53b57RwBCjXfMMq0JCPvuePLK40NC8uCAi+wr5Er0fAWz1JiaA+dowposoi6RxBtyHCaNHMDVGMLh1j+IL+pTOyi6fk=,iv:gssOMmR0DDQC4WjMVXTD/zqbQa8qlBr9ZZWF15W0WnE=,tag:DORTxQfCmpVjDjyGSNH7dw==,type:str] + pgp: + - created_at: "2026-05-23T20:58:22Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAxK/JaB2/SdtAQ//bbr0oza/X6GG43ay9coZbb+0aptj3pGzQqT1ND6nsI34 + iY3IZaMZIti+j/BS5kEfmRn56WZSx6EcbSrlbiyL5NZw9R4/bGRd848rOLwMvuYO + 8Usei9jHdpHiPvKBZnZXaXGU8E27L0Y/LCxSIFOXbyHzHogjz3JmtJQsYpSC+ue6 + mIRrSAJPALrqEL+DZ2bl5UYlBIRXdtIe/jL1CFCJhULt+EjJw72T62DZK/jaNZTj + eint63+IFZSxx5e5vrAeQB+p2EDsp6c5NbDrlgQWb8/J1q/G5bG4KxBs/0hum7OW + /sSsIDb4Qb8U/axt5LduV6AkMXXsclNLQU/LbFAbBRcV8Lvh11f0U3V/UnqUdmvp + efesb5VQh1x0uWjzobxaioLEV/YYbWx8binvuJ3MBHKp6E2xj7IrBTVl0MWgjEou + ZbQDF8DvxA49xEnJyOviL2/zjnV1kXy+Q+BKZga3pr8AnBHA8Ftbsvmk6CyDEM0R + i4FAUOVa9VWiszoOaqyn1Fl02YlweFmgzuFjd3wi74Tbi6RE37rN/vBKySbnRQYl + rFUU3SQlztxd4UBAXBo6gQKTz5B4rehvKVye2mmqEE9bas/lCWAKVJ7+3+0NQdA2 + lp/X7h7DRSD2Qkd35SzxkJz7P86rd0LM1aOu87psxYavEWw6vFs2ErDkSeqDn1DU + aAEJAhDb1s+jpDUa3GvVZjoiiCyutI018jfJU1vi12PGktg4KJcXBx66R/nLItO2 + ba6o66scIiAJZ+jYymW6RbJTI7XRHJp4Cs8COhpMRQeOGwEHFGGL2rpGd3KrOLQe + 0/C6EmrJvGpl + =atNE + -----END PGP MESSAGE----- + fp: EF643F59E008414882232C78FFA8331EEB7D6B70 + - created_at: "2026-05-23T20:58:22Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQEMA1QflAioE8i3AQf+NkUGCBrTCkkyl+iBb6P1IWLDGqAY8s20mBZ7G3plKE/J + UrIe947letj/8EA+yoN0uzjwEkh3rDLtZrOLTSgflq1GMpdVhdaTbS71fD3kghJQ + P9tz0zDQEgXHBi+2q7iRrEETx/cu7UDNkSCNvQbWvDmo8MfbSBy+VFCknfupdQxj + 9hlq4kBA0pckPCY8V7E05nDhQntS8wpXIEO1SWiSuiGg+p4yFlvNzWNfhLyEFHxL + BZHVVIU/mzyClMajjLJWjKI1LSgHXXIa28tgdrtiBZOsF+CWveYqJlRJh9NUepJI + ZSeFNhyWmnS9ZkQu5BUyb7+oRxfq2NY51T76Xbo8gNJeAZWwyr1sj1wjubuVeNMF + aU6FiynYWr3I35JRVghTMJ93CnPl+NTpWnQuHpq1bzEGe2u8BMFhgrTu2yMD23VQ + eGien6SqfEbA/wAiz9ZaUgTQH8UyHpliteZ8/SQgkw== + =UJvq + -----END PGP MESSAGE----- + fp: 21C9579E6503CA815A68ABD8541F9408A813C8B7 + - created_at: "2026-05-23T20:58:22Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAz5uSgHG2iMJAQ/+O5JOJfDp/BuBCuXDQVUgJagspQO6LZ/MLrl9qH282AMf + MdgN5M/WjbOv6WZDCMg4nfXps1XgzUEiaA/1m4PxHlMmxjEoQHAE51GMcxsXg+B1 + lM+8uJ1+js1sdDX4xsZtJpbVxJKIbPuhF7oM950oDlL2+UKhUbPlCoxeOihlkVGa + RqHJ/M74xkyKH281oRI5bllJaAroBnXVSFIvbCxA7ts/O7YJPKBowTIj62Kye9Ra + aHC11bPy2RlJCcFZJjPSdnXvzUMpfzEd6O72VUtMBBQZn/in7efutC8FwpRYuUW7 + vSofxUN5n6Mtb8A1XSMFD/nfXVc/pM6Cu7kdtHSwSKgbKKf6mrCeVgaM9xcG0t2W + 9yEtWvkdvOOSqz/vd1vkftbBWcCejX7bktfmD408CJAs1bjzz5CyrDoWcnYmbxFY + 6N4rhMDRMTe19VH2UQ4EvSjQjmmYCspnUW3/78zi5kU1ijyQy13UpbgwulU7tSGc + KKtBjPoy6mLIVl0YhnEJZWD/XPIRWyW+0s+7m70YXCWSVipvCelEE8oPWjf8PLaE + J85crlZGkSRcRO7yOP/YtB9ZnajgaF33zJU3ZWr0C/IXj2TeepZp/JUteD2H/LRf + 9YJzOFYDOFIWcdmaTzJLBEaefWcDjT6wkIf6TBqQRMLsu8JUwy9VwFcsi/d5aMXS + XgEQqSxYb1B39OR0sS1Xpw0/CFe4imBPuG3w0tOAyM3DbPWYY1kZYIRZenV1ZIOS + aRZJh086kuWgHYB76VoNzDK3QperWvHL/8CT2g3HuPiVGSrrXwxCYXk5+UXB9bQ= + =Xx91 + -----END PGP MESSAGE----- + fp: 18DFCE01456DAB52EA38A6584EDC64F35FA1D6A5 + - created_at: "2026-05-23T20:58:22Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4DsZXvxFXTXoQSAQdA0rZTVdySF9nUiz7ZyFJgq1tojyLojGTgE4UIEJzFSTUw + 9y4kbGn1cWMpAqr+sE3WHV9p7v6kgm/XdUjXGN4DadpUbiYx6sQW2Jov6Km2EYhq + 0l4BawupjX25wi7c2yR5iGdxYS8oCYVmGgcAB3T96v8VsXpkAOYQAOOh7B9GQIxm + hB3cFQLCy2un3VvBsiKGFMA2FhZYBOuaEwP/KmWnPv0IPIRH4by6LDB0xgq8MUNz + =xoVE + -----END PGP MESSAGE----- + fp: 9633412309CCB83BFA39BA5F2FEF746201D7FCFE + - created_at: "2026-05-23T20:58:22Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4DerEtaFuTeewSAQdAgcGcZ3BT6lsJ8FxkMghxg5/PZLtIzNeJaEUbxN0EFhsw + uM+Lec3k9BJSUJK8GeVmesYxQh8vP6Yi/+m2LnGjHXzkQg8Bx1HJzuC/Ap36rC6N + 0l4Bxj1URTsRD4yILEA3TY4Dn9St9uOtodJcf5YdAKvmeb3Uwy//huNnA1eK7b+v + WRHcU2K+GgkSzLiRLZTc/nMrrCQ/P5HzwYHmP2rypFX7kxXlPd3K6yMZWTiSgYZd + =gZLQ + -----END PGP MESSAGE----- + fp: 057870A2C72CD82566A3EC983695F4FCBCAE4912 + - created_at: "2026-05-23T20:58:22Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAxjNhCKPP69fAQ//YGOLOFtORNbOu+KFCtGcJBXQMy6Ej3/tePVuDi2vmqLD + 3Dz6stB9D+BmBbcgbFlDA+g7Vi6DD+zcze9wM10iuc9t9ucAuQ7B/ymSvJc4MrYn + MJFvQv5IYgWJmzXLYEFYYpmZPGG3hSHSgWIPs+574wEA/L867ktguW6ZD3ZuMn3E + yjCTeT/ZkGjuIpGqMu2/o9Wvc+RYgWlCB69D8kTHtnbFzbqEzvKU5/zte5ThchA+ + QZwFd/gk3o1G/7WOYJJ6CbBSOQaSrfm0mnb6sppNPdOAQtqHVSFVX5vX96gXsht/ + AkrvD6/2R5eNzbqRaU83cg7c5far49xoBbL6czreWY3D56yK4BJbrrg9mK7oCEfO + GaRDFFD7R4LJPfVx2xDoIQ3Hyp4E3dz4nyJx0Kg7NSEt7soOb5MnZ+04LLAiHbaT + qZr618V530uw3qaCsYcgHy+WsZXXlqXQey3A7jphi3u9Kvn9UjeegjNvpOrMk6g1 + RhGzv72G0wjZnzjTjPlzeROHaQ6RPgfpkZjEcVZNZkfAgAbB3XPgCFGKz4qvx9MP + 4eHIlBSJizLzSi519o+0i5PwrZdEf9L4RUVxgQgdJXMh1JaydVh5DOU+xomdStD5 + Maymkt8fSgYgDaS953YA2e04PrkXCH0EHZ62T9EMxreEoU3nYTmw/TGx7RfU+wzS + XgEuQkLWSToJ40/Ir3obDA246yv7J2FpmPwG4oFypkM5xe1WjlMlk90b9RBhUgXk + ylRXXLBzau6mtbPOa7LGdVyVs2DClWQo9BoK+dxEsnW+TR144O4UmZEfifJXvgQ= + =ympd + -----END PGP MESSAGE----- + fp: F38C9D4228FC6F674E322D9C3326D914EB9B8F55 + - created_at: "2026-05-23T20:58:22Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA46L6MuPqfJqARAAshm2x7wX/9g3XJtSN0AnSeCwSHO1I4+ebLKOsB7zcXh8 + hrVO3694jQcU9L01H7jGYw4lNNzBd61/uVE5AvMq4Sqn9iH3MFNESbAEOWVV+TRf + 53JMg9C/aZfde8gHgHPaiVXlCBVEVY9CqHpUXUKDmEE7iRb5P4DuMxOmybDYZGzY + 4c5Ke1MFMkGRmAtsT1qLrT2vh+F0CX4JwpMkxCmOzSWAXbwrVOigJ35l5zM6vme4 + 5EQu9jI8FApTxVchZbr0v3UOKxp5OebqC0jGeznZNf4qb0qnsvuowY6IIw5Tl3/q + H4TLq5EUOVqTC1voIWY/gMjieiW1gtr6vASy4MvbswsZLc26YVE9IbHzAOUWDN2o + f2iQ3aZYuINvniD23XtM0TKepDXWq5eF+AJpmyP/LL8sYvSnWFD+muK3O657djEu + yGZs2EFTrkiUvhBq3apOOYiU0eOi4Aq6UeEbOsLENnQrBRXuHEm4KUSwzOitVwJ1 + ByxQTu7wzY727SOR2hzjMC0LI602WGpEQU7ech5L4uWqtMFwaBP9HnUamcofKqqt + 1vI2BevsJfQ0rtTE6GWseHt702lllTGe3RnHWc6YsMWLwUfRdBPggMW37hAPPcfO + ytbU3RJIxx4vImRtXhkI5yvbpFQrooz1zSeXWaitPE5jmmiKe9IRStLnfiq9E2TS + XgFVuQM8K0LgUYEoAipvafhnC3ohfGsM2AYd36EoaMNLeQ2ZZEiV06/Y3EWoI0iM + aqRLwyBvTuDOc5BK32nCbAgUbbPJjPhqWaoNp5ymCBV76oW613gApkzoUF+OIUU= + =KKaI + -----END PGP MESSAGE----- + fp: 8996B62CBD159DCADD3B6DC08BB33A8ABCF7BC4A + - created_at: "2026-05-23T20:58:22Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4DQrf1tCqiJxoSAQdA8YKD21h5POTLPf04KvGN93omFgkYO+Y8Kc0jM0vdqm8w + 3zYRaLsDjdh8Zd89/HhHJUfLrTp/IJ0n81sK0ZjznbXKxgkseGthMzof+L7BnPAp + 0l4BnAs9iZS4q2LZVS7ySBP89xLmF97qhK2jagMNSAwq8Afxbcw8oQAVQmeyYfxx + X59irIHjI1ugO4o1WnTN67nTQjU5msbVBs0eALrw3jobzFHRL67fS0a4Soa59LTY + =ZHIU + -----END PGP MESSAGE----- + fp: B71138A6A8964A3C3B8899857B4F70C356765BAB + - created_at: "2026-05-23T20:58:22Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4DzAGzViGx4qcSAQdAN7rRlv3dMoFOfj9eHgf+0H8521b32nWqySUdriEy6Tcw + gjuReMBpKQOgUfuhIiWkHIKNtNgMrYWiC20ESOXX5b9uYZNpqHCgHQPlX0lEeGim + 0lgBOieL7mSEq4wkWLCSv4sBAmkQA+dnugBeF+TrlqKQTZsbe/Z+jNG4ZrHRvdqi + 4I5It+uaRV9Vrul1c6H7fNreRPUd4hNyJwU7gZQ+vU2WyAmgqerxE1Wb + =gplT + -----END PGP MESSAGE----- + fp: D2E9C0807BF681F5E164DAFC5EE1B61CD90954CD + - created_at: "2026-05-23T20:58:22Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA2pVdGTIrZI+ARAAjWK8mU99VcnM/Ckzm+YsZFTwnz4PDAenDDdZ1OOz5IXe + tS4SQPcQlSSOuXEkFLJMmm8QVxtUC3Gh4nF7o+7OygT+0ZXOrB7jFgg10+v/KVA9 + hSlqBdsMxcC0OzBtkGyAOXOxqnTVubuHEGyGpIryHt1/lthUUZHBbjgw7P0Tw2/U + sYK5j5YbqhyBl20gyZorkTTq7pHfVXDVtpe75+ZkqbOg4S6HgW3/dl+v6N0TLfRs + GVl0fUlWIK/akGCB71zdwJs2I1qTeMTlL6v+XSUdXj0YV+5fjh3wf8qzN9geIjQK + ybxGFWDKCAgTMnqoFF5BCL23hFtnCbTtLN1wQT7/m7zpjaBKHOBXZOGXYZCMGZui + sBsUvPANgNdfOse9H2aABQvUQh8WqFw8S73GasvrZHAwEmvnXzocMJd+kUovzmQu + 9FBk5UkcgXfmxeamoP8C700vh4zI+sKz6uEW0+AuVtLlLVqlb2w21kTc+ArZW52n + HLolH5q3Wj6pKuuFCWKr6UgLFcq2w4QngB2p+UABHU3RbwXIra7prDXCUcNC5iCn + ElRFY7OZ3nbHOf9oaW/MitcfszVLyl0ueoay6qxdlIGdXKRGpqxHqqr+92INV/iz + 6CRoAsTqVq1a7ZuAaUdJPvfKVAHHEHjPwlrOc9cXvykG0iQKsRzgqiOtPiGQShnU + aAEJAhDSqCwywHDnQ7X9ZWIzPjwvqyHpEVez8zYh3vpgKpsLb9uL+JizZjV02HMe + nhiL+4o/aNjJgGJWph1uPFhU4wO4AavnNBsHbJSiL/1yTS96hdf8d+gB41yVLU3e + kBkDFLKkIBkU + =aRLd + -----END PGP MESSAGE----- + fp: 878FEA3CB6A6F6E7CD80ECBE28506E3585F9F533 + - created_at: "2026-05-23T20:58:22Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4DKKbvh61jX5USAQdABId/P8ozRgJ4ItF1zvxp98aH+g3LZ6UGnxjYjtDxjEIw + VmyerznjOLnpz0EobXRRoot1Lo82Va64HQmXt26LG3gFY1HVp0WOnIZXa/CUoUb8 + 1GgBCQIQloFxKcgFTiRidaJfN7hSeQLleiEe3aifZUyJj8niTmBaY29t+CSoA46N + xZzX1AlxVjfmputhYdTyOYSJtGrj7otmnUN2P+55pjz4L2qCYAEKi1+ibqgpmJh/ + bETQsT6WKJ8FXA== + =Ci7L + -----END PGP MESSAGE----- + fp: 41FFAF3D519CF5C039FBD8414BCC213729AF0E49 + unencrypted_suffix: _unencrypted + version: 3.13.1 diff --git a/inventories/z9/host_vars/rt1.yaml b/inventories/z9/host_vars/rt1.yaml new file mode 100644 index 0000000..876776a --- /dev/null +++ b/inventories/z9/host_vars/rt1.yaml @@ -0,0 +1,7 @@ +systemd_networkd__config_dir: 'resources/z9/rt1/systemd_networkd/' +systemd_networkd__global_config: "{{ lookup('ansible.builtin.file', 'resources/z9/rt1/systemd_networkd_global_config.conf') }}" +nftables__config: "{{ lookup('ansible.builtin.file', 'resources/z9/rt1/nftables/nftables.conf') }}" +ansible_pull__timer_on_calendar: "*-*-* 04:00:00 Europe/Berlin" +ansible_pull__timer_randomized_delay_sec: 0min +unbound_access_control: [ "10.89.208.0/20" ] +kea_dhcp__include_vars: resources/z9/rt1/kea_dhcp.yaml diff --git a/inventories/z9/hosts.yaml b/inventories/z9/hosts.yaml index eab3880..407aa2f 100644 --- a/inventories/z9/hosts.yaml +++ b/inventories/z9/hosts.yaml @@ -14,6 +14,9 @@ all: yate: ansible_host: yate.ccchh.net ansible_user: chaos + rt1: + ansible_host: rt1.ccchh.net + ansible_user: chaos certbot_hosts: hosts: dooris: @@ -35,6 +38,7 @@ infrastructure_authorized_keys_hosts: light: waybackproxy: yate: + rt1: nginx_hosts: hosts: dooris: @@ -46,11 +50,24 @@ ola_hosts: proxmox_vm_template_hosts: hosts: thinkcccore0: +systemd_networkd_hosts: + hosts: + rt1: +nftables_hosts: + hosts: + rt1: +unbound_hosts: + hosts: + rt1: +kea_dhcp_hosts: + hosts: + rt1: alloy_hosts: hosts: light: yate: dooris: + rt1: ansible_pull_hosts: hosts: dooris: @@ -59,3 +76,4 @@ ansible_pull_hosts: yate: secrets_hosts: hosts: + rt1: diff --git a/playbooks/deploy.yaml b/playbooks/deploy.yaml index b7ce104..54d4098 100644 --- a/playbooks/deploy.yaml +++ b/playbooks/deploy.yaml @@ -27,6 +27,20 @@ tags: - nftables +- name: Ensure unbound deployment on unbound_hosts + hosts: unbound_hosts + roles: + - unbound + tags: + - unbound + +- name: Ensure kea_dhcp deployment on kea_dhcp_hosts + hosts: kea_dhcp_hosts + roles: + - kea_dhcp + tags: + - kea_dhcp + - name: Ensure deployment of infrastructure authorized keys hosts: infrastructure_authorized_keys_hosts roles: diff --git a/resources/z9/rt1/kea_dhcp.yaml b/resources/z9/rt1/kea_dhcp.yaml new file mode 100644 index 0000000..d191881 --- /dev/null +++ b/resources/z9/rt1/kea_dhcp.yaml @@ -0,0 +1,293 @@ +kea_dhcp__dns_servers: + v4: + - 185.161.129.134 + v6: + - 2a07:c481::1:2 + +kea_dhcp__dhcp4: + enable: true + interfaces: [ "netlan.51", "netlan.52", "netlan.54" ] + control-sockets: + - socket-name: /var/run/kea-dhcp4-ctrl-agent.sock + socket-type: unix + lease-database: + type: memfile + persist: true + option-data: + - name: "domain-name-servers" + code: 6 + csv-format: true + data: "{{ kea_dhcp__dns_servers.v4 | join(',') }}" + subnets: + - id: 1 + subnet: 10.89.208.0/22 + pools: + - pool: "10.89.208.32 - 10.89.211.250" + reservations: + - ip-address: 10.89.208.11 + hostname: beamer + hw-address: "ac:87:a3:18:9e:01" + - ip-address: 10.89.208.12 + hostname: Brother-CCCHH + hw-address: "00:80:77:04:3a:55" + - ip-address: 10.89.208.13 + hostname: muzak + hw-address: "00:11:24:5f:4f:80" + - ip-address: 10.89.208.14 + hostname: Big-Room-Beamer + hw-address: "64:d2:c4:db:08:5c" + - ip-address: 10.89.208.16 + hostname: dooris + hw-address: "bc:24:11:b3:93:9c" + - ip-address: 10.89.208.17 + hostname: hmdooris-ccu + hw-address: "bc:24:11:5f:2d:b1" + - ip-address: 10.89.208.27 + hostname: cisco-slm248p + hw-address: "00:23:eb:b0:fc:3f" + - ip-address: 10.89.208.47 + hw-address: "6c:df:fb:0b:34:21" + - ip-address: 10.89.208.48 + hw-address: "6c:df:fb:0d:91:63" + - ip-address: 10.89.209.28 + hostname: hp-color + hw-address: "3c:52:82:29:21:79" + - ip-address: 10.89.209.29 + hostname: dooris-ng + hw-address: "6c:4b:90:19:21:a1" + - ip-address: 10.89.209.166 + hostname: encoder-ccchh + hw-address: "00:4e:01:a2:40:d7" + - ip-address: 10.89.209.254 + hostname: ki10 + hw-address: "dc:a6:32:a9:ff:82" + option-data: + - name: routers, + csv-format: true + data: 10.89.208.1 + - id: 2 + subnet: 10.89.212.0/24 + pools: + - pool: "10.89.212.32 - 10.89.212.250" + reservations: + - ip-address: 10.89.212.3 + hostname: prusamk3 + hw-address: "10:9c:70:2e:59:3e" + - ip-address: 10.89.212.4 + hostname: prusamk4 + hw-address: "10:9c:70:2e:6e:f0" + - ip-address: 10.89.212.11 + hostname: Ziggy + hw-address: "44:17:93:53:65:57" + - ip-address: 10.89.212.12 + hostname: legacy + hw-address: "00:15:65:a1:ed:98" + - ip-address: 10.89.212.23 + hostname: foobarpay + hw-address: "f4:f2:6d:09:a6:73" + - ip-address: 10.89.212.24 + hostname: foobackup + hw-address: "bc:24:11:20:1a:a8" + - ip-address: 10.89.212.27 + hostname: ender3v2-sonic-pad + hw-address: "fc:ee:91:00:0e:14" + - ip-address: 10.89.212.31 + hostname: octopi + hw-address: "b8:27:eb:0f:d8:09" + - ip-address: 10.89.212.32 + hostname: 433mhz-bridge + hw-address: "0c:b8:15:fe:e3:34" + - ip-address: 10.89.212.33 + hostname: wled-kueche + hw-address: "30:ae:a4:7a:8d:a0" + - ip-address: 10.89.212.34 + hostname: wled-serverschrank + hw-address: "18:fe:34:a6:64:76" + - ip-address: 10.89.212.35 + hostname: wled-couch + hw-address: "64:b7:08:40:ab:c0" + - ip-address: 10.89.212.36 + hostname: laser + hw-address: "b8:27:eb:be:38:fa" + - ip-address: 10.89.212.37 + hostname: laser-eth + hw-address: "b8:27:eb:eb:6d:af" + - ip-address: 10.89.212.42 + hostname: t-mix + hw-address: "40:a5:ef:d9:eb:93" + - ip-address: 10.89.212.86 + hostname: fritz-fon + hw-address: "00:1f:3f:c9:e5:b2" + - ip-address: 10.89.212.211 + hostname: hauptraum-esphome + hw-address: "e8:db:84:e8:18:d2" + - ip-address: 10.89.212.212 + hostname: werkstatt-esphome + hw-address: "3c:71:bf:26:42:32" + - ip-address: 10.89.212.213 + hostname: ir-bridge-beamer + hw-address: "8c:ce:4e:51:93:dd" + - ip-address: 10.89.212.215 + hostname: pi-dmx-werkstatt + hw-address: "b8:27:eb:65:e5:31" + - ip-address: 10.89.212.227 + hostname: SIP-T46S + hw-address: "80:5e:c0:09:bf:55" + - ip-address: 10.89.212.230 + hostname: SIP-T46S + hw-address: "80:5e:c0:22:33:08" + - ip-address: 10.89.212.232 + hostname: staubi + hw-address: "b8:4d:43:98:51:2b" + - ip-address: 10.89.212.233 + hostname: staubiv2 + hw-address: "70:c9:32:82:25:b2" + - ip-address: 10.89.212.234 + hostname: AtemMini + hw-address: "7c:2e:0d:13:72:a8" + - ip-address: 10.89.212.235 + hostname: okilaser + hw-address: "2c:ff:65:22:b4:63" + - ip-address: 10.89.212.236 + hw-address: "b8:27:eb:29:bd:77" + option-data: + - name: routers, + csv-format: true + data: 10.89.212.1 + - id: 3 + subnet: 10.89.213.0/24 + pools: + - pool: "10.89.213.32 - 10.89.213.250" + reservations: + - ip-address: 10.89.213.2 + hostname: sw-rack-1 + hw-address: "F0:9F:C2:10:C3:AA" + - ip-address: 10.89.213.3 + hostname: sw-rack-2-peo + hw-address: "44:d9:e7:06:69:5d" + - ip-address: 10.89.213.4 + hostname: sw-main-1 + hw-address: "a8:9c:6c:16:df:cc" + - ip-address: 10.89.213.5 + hostname: sw-main-2 + hw-address: "a8:9c:6c:16:e8:86" + - ip-address: 10.89.213.6 + hostname: sw-shop-1 + hw-address: "C0:4A:00:FB:DA:C5" + - ip-address: 10.89.213.7 + hostname: sw-shop-2-peo + hw-address: "f4:e2:c6:bf:20:ee" + - ip-address: 10.89.213.8 + hostname: sw-shop-3-peo + hw-address: "d8:b3:70:85:72:76" + - ip-address: 10.89.213.11 + hostname: pve01 + hw-address: "38:05:25:30:80:35" + - ip-address: 10.89.213.12 + hostname: pve02 + hw-address: "b8:85:84:b1:57:b6" + - ip-address: 10.89.213.13 + hostname: pve03 + hw-address: "98:fa:9b:a2:ed:e8" + - ip-address: 10.89.213.15 + hostname: pbs + hw-address: "BC:24:11:D6:2C:81" + - ip-address: 10.89.213.21 + hostname: unifi + hw-address: "BC:24:11:25:77:60" + - ip-address: 10.89.213.22 + hostname: club-assistant + hw-address: "7a:55:61:c3:a2:89" + - ip-address: 10.89.213.23 + hostname: automation + hw-address: "f2:20:75:5a:2f:8c" + - ip-address: 10.89.213.24 + hostname: yate + hw-address: "bc:24:11:73:3e:f7" + - ip-address: 10.89.213.25 + hostname: ptouch-print-server + hw-address: "bc:24:11:f2:cf:8f" + - ip-address: 10.89.213.26 + hostname: mqtt + hw-address: "bc:24:11:48:85:73" + - ip-address: 10.89.213.27 + hostname: factorio + hw-address: "bc:24:11:a3:43:7f" + - ip-address: 10.89.213.28 + hostname: light + hw-address: "72:61:ea:e6:49:e3" + - ip-address: 10.89.213.29 + hostname: homematic + hw-address: "fe:3a:42:77:3a:be" + - ip-address: 10.89.213.30 + hostname: proxmox-backup-server + hw-address: "8a:48:dd:a3:22:40" + option-data: + - name: routers, + csv-format: true + data: 10.89.213.1 + +kea_dhcp__dhcp6: + enable: true + interfaces: [ "netlan.51", "netlan.52", "netlan.54" ] + control-sockets: + - socket-name: /var/run/kea-dhcp6-ctrl-agent.sock + socket-type: unix + lease-database: + type: memfile + persist: true + option-data: + - name: "dns-servers" + code: 23 + csv-format: true + data: "{{ kea_dhcp__dns_servers.v6 | join(',') }}" + subnets: + - id: 1 + subnet: "2a07:c481:1:33::/64" + pools: + - pool: "2a07:c481:1:33::1:1 - 2a07:c481:1:33::FFFF:FFFF" + - id: 2 + subnet: "2a07:c481:1:34::/64" + pools: + - pool: "2a07:c481:1:34::1:1 - 2a07:c481:1:34::FFFF:FFFF" + - id: 3 + subnet: "2a07:c481:1:36::/64" + pools: + - pool: "2a07:c481:1:36::1:1 - 2a07:c481:1:36::FFFF:FFFF" + reservations: + - ip-address: "2a07:c481:1:36::2" + hostname: sw-rack-1 + hw-address: "F0:9F:C2:10:C3:AA" + - ip-address: "2a07:c481:1:36::3" + hostname: sw-rack-2-peo + hw-address: "44:d9:e7:06:69:5d" + - ip-address: "2a07:c481:1:36::4" + hostname: sw-main-1 + hw-address: "a8:9c:6c:16:df:cc" + - ip-address: "2a07:c481:1:36::5" + hostname: sw-main-2 + hw-address: "a8:9c:6c:16:e8:86" + - ip-address: "2a07:c481:1:36::6" + hostname: sw-shop-1 + hw-address: "C0:4A:00:FB:DA:C5" + - ip-address: "2a07:c481:1:36::7" + hostname: sw-shop-2-peo + hw-address: "f4:e2:c6:bf:20:ee" + - ip-address: "2a07:c481:1:36::8" + hostname: sw-shop-3-peo + hw-address: "d8:b3:70:85:72:76" + - ip-address: "2a07:c481:1:36::b" + hostname: pve01 + hw-address: "38:05:25:30:80:35" + - ip-address: "2a07:c481:1:36::c" + hostname: pve02 + hw-address: "b8:85:84:b1:57:b6" + - ip-address: "2a07:c481:1:36::d" + hostname: pve03 + hw-address: "98:fa:9b:a2:ed:e8" + - ip-address: "2a07:c481:1:36::f" + hostname: pbs + hw-address: "BC:24:11:D6:2C:81" + - ip-address: "2a07:c481:1:36::14" + hostname: unifi + hw-address: "BC:24:11:25:77:60" diff --git a/resources/z9/rt1/nftables/nftables.conf b/resources/z9/rt1/nftables/nftables.conf new file mode 100644 index 0000000..842ca04 --- /dev/null +++ b/resources/z9/rt1/nftables/nftables.conf @@ -0,0 +1,114 @@ +#!/usr/sbin/nft -f + +## Variables + +# Hosts + + +# Interfaces +define if_netwan = "netwan" +define if_netlan = "netlan" +define if_wg55_management = "wg55" +define if_netwan_400_fux_uplink = "netwan.400" +define if_netlan_51_clients = "netlan.51" +define if_netlan_52_iot = "netlan.52" +define if_netlan_53_public = "netlan.53" +define if_netlan_54_management = "netlan.54" + +# Interface Groups +define wan_ifs = { $if_netwan_400_fux_uplink } +define lan_ifs = { $if_netlan_51_clients, + $if_netlan_52_iot, + $if_netlan_53_public, + $if_netlan_54_management } +define v4_exposed_ifs = { $if_netlan_53_public } +define v6_exposed_ifs = { $if_netlan_53_public } +define v4_nat_ifs = { $if_netlan_51_clients, + $if_netlan_52_iot, + $if_netlan_54_management } + + +## Rules + +table inet reverse-path-forwarding { + chain rpf-filter { + type filter hook prerouting priority mangle + 10; policy drop; + + # Only allow packets if their source address is routed via their incoming interface. + # https://github.com/NixOS/nixpkgs/blob/d9d87c51960050e89c79e4025082ed965e770d68/nixos/modules/services/networking/firewall-nftables.nix#L100 + fib saddr . mark . iif oif exists accept + } +} + +table inet host { + chain input { + type filter hook input priority filter; policy drop; + + iifname "lo" accept comment "allow loopback" + + ct state invalid drop + ct state established,related accept + + ip protocol icmp accept + # ICMPv6 + # https://datatracker.ietf.org/doc/html/rfc4890#autoid-24 + # Allowlist consisting of: "Traffic That Must Not Be Dropped" and "Traffic That Normally Should Not Be Dropped" + # Error messages that are essential to the establishment and maintenance of communications: + icmpv6 type { destination-unreachable, packet-too-big } accept + icmpv6 type { time-exceeded } accept + icmpv6 type { parameter-problem } accept + # Connectivity checking messages: + icmpv6 type { echo-request, echo-reply } accept + # Address Configuration and Router Selection messages: + icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, ind-neighbor-solicit, ind-neighbor-advert } accept + # Link-Local Multicast Receiver Notification messages: + icmpv6 type { mld-listener-query, mld-listener-report, mld-listener-done, mld2-listener-report } accept + # SEND Certificate Path Notification messages: + icmpv6 type { 148, 149 } accept + # Multicast Router Discovery messages: + icmpv6 type { 151, 152, 153 } accept + + # Allow SSH access. + tcp dport 22 accept comment "allow ssh access" + + # Allow WireGuard access. + udp dport 51820 accept comment "allow WireGuard access" + + # Allow DHCP server access. + iifname { $lan_ifs } udp dport 67 accept comment "allow dhcp server access" + + # Allow DNS server access from lan_ifs + iifname { $lan_ifs, $if_wg55_management } udp dport 53 accept comment "allow dns server access from lan_ifs" + } +} + +table ip v4nat { + chain prerouting { + type nat hook prerouting priority dstnat; policy accept; + } + + chain postrouting { + type nat hook postrouting priority srcnat; policy accept; + + iifname { $v4_nat_ifs, $if_wg55_management } oifname $wan_ifs masquerade + } +} + +table inet forward { + chain forward { + type filter hook forward priority filter; policy drop; + + ct state invalid drop + ct state established,related accept + + # Allow internet access. + iifname { $lan_ifs, $if_wg55_management } oifname $wan_ifs accept comment "allow internet access" + + # Allow access to exposed networks from internet. + meta nfproto ipv4 oifname $v4_exposed_ifs accept comment "allow v4 exposed network access" + meta nfproto ipv6 oifname $v6_exposed_ifs accept comment "allow v6 exposed network access" + + # Allow clients and managment to most + iifname { $if_netlan_51_clients, $if_netlan_54_management, $if_wg55_management } oifname $lan_ifs accept comment "allow clients and managment to lan_ifs" + } +} diff --git a/resources/z9/rt1/systemd_networkd/00-netlan.link b/resources/z9/rt1/systemd_networkd/00-netlan.link new file mode 100644 index 0000000..c2e2470 --- /dev/null +++ b/resources/z9/rt1/systemd_networkd/00-netlan.link @@ -0,0 +1,6 @@ +[Match] +MACAddress=BC:24:11:72:A3:27 +Type=ether + +[Link] +Name=netlan diff --git a/resources/z9/rt1/systemd_networkd/00-netwan.link b/resources/z9/rt1/systemd_networkd/00-netwan.link new file mode 100644 index 0000000..523e18a --- /dev/null +++ b/resources/z9/rt1/systemd_networkd/00-netwan.link @@ -0,0 +1,6 @@ +[Match] +MACAddress=BC:24:11:CF:65:57 +Type=ether + +[Link] +Name=netwan diff --git a/resources/z9/rt1/systemd_networkd/10-netlan.51.netdev b/resources/z9/rt1/systemd_networkd/10-netlan.51.netdev new file mode 100644 index 0000000..b951ecc --- /dev/null +++ b/resources/z9/rt1/systemd_networkd/10-netlan.51.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=netlan.51 +Kind=vlan + +[VLAN] +Id=51 + diff --git a/resources/z9/rt1/systemd_networkd/10-netlan.52.netdev b/resources/z9/rt1/systemd_networkd/10-netlan.52.netdev new file mode 100644 index 0000000..1f345c7 --- /dev/null +++ b/resources/z9/rt1/systemd_networkd/10-netlan.52.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=netlan.52 +Kind=vlan + +[VLAN] +Id=52 + diff --git a/resources/z9/rt1/systemd_networkd/10-netlan.53.netdev b/resources/z9/rt1/systemd_networkd/10-netlan.53.netdev new file mode 100644 index 0000000..c6dab81 --- /dev/null +++ b/resources/z9/rt1/systemd_networkd/10-netlan.53.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=netlan.53 +Kind=vlan + +[VLAN] +Id=53 + diff --git a/resources/z9/rt1/systemd_networkd/10-netlan.54.netdev b/resources/z9/rt1/systemd_networkd/10-netlan.54.netdev new file mode 100644 index 0000000..6271e6c --- /dev/null +++ b/resources/z9/rt1/systemd_networkd/10-netlan.54.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=netlan.54 +Kind=vlan + +[VLAN] +Id=54 + diff --git a/resources/z9/rt1/systemd_networkd/10-netwan.400.netdev b/resources/z9/rt1/systemd_networkd/10-netwan.400.netdev new file mode 100644 index 0000000..e0b6afc --- /dev/null +++ b/resources/z9/rt1/systemd_networkd/10-netwan.400.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=netwan.400 +Kind=vlan + +[VLAN] +Id=400 + diff --git a/resources/z9/rt1/systemd_networkd/10-wg55.netdev b/resources/z9/rt1/systemd_networkd/10-wg55.netdev new file mode 100644 index 0000000..b3e41a6 --- /dev/null +++ b/resources/z9/rt1/systemd_networkd/10-wg55.netdev @@ -0,0 +1,90 @@ +[NetDev] +Description=Admin-Wireguard +Kind=wireguard +Name=wg55 + +[WireGuard] +ListenPort=51820 +PrivateKeyFile=/etc/ansible_secrets/wireguard_wg55_privat_key + +# WireGuard Peers + +[WireGuardPeer] +# friendly_name = stb +AllowedIPs = 10.89.214.2/32,2a07:c481:1:37::2/128 +PublicKey = vILSL4dbaC5IaTsRhJviamV18ssxWSj+qLVyowLQ214= +PersistentKeepalive = 30 + +[WireGuardPeer] +# friendly_name = fi +AllowedIPs = 10.89.214.3/32,2a07:c481:1:37::3/128 +PublicKey = UHi/if5uW2V3+8Q3R+uk6/XpRi4fPXbw7chsKI4xlkI= +PresharedKeyFile = /etc/ansible_secrets/wireguard_wg55_peer_fi_psk + +[WireGuardPeer] +# friendly_name = jtbx +AllowedIPs = 10.89.214.4/32,2a07:c481:1:37::4/128 +PublicKey = NyyEqdWgScgsnTF8Zz/Om4Lc84fdFMwVtvaCmLEkUlQ= + +[WireGuardPeer] +# friendly_name = June +AllowedIPs = 10.89.214.6/32,2a07:c481:1:37::6/128 +PublicKey = 6jAEB+f9przBGxPhuvv9U9gvZDEBQNqpQSD0BoGqXQQ= +PresharedKeyFile = /etc/ansible_secrets/wireguard_wg55_peer_June_psk + +[WireGuardPeer] +# friendly_name = Max +AllowedIPs = 10.89.214.7/32,2a07:c481:1:37::7/128 +PublicKey = oC1hJjtlAgLX/CmbwTC+LPmd1uwluQTwsN8RaMNmHn0= +PresharedKeyFile = /etc/ansible_secrets/wireguard_wg55_peer_Max_psk + +[WireGuardPeer] +# friendly_name = dario +AllowedIPs = 10.89.214.9/32,2a07:c481:1:37::9/128 +PublicKey = bYF2EGRGpEGjiKcasi/oaWoWeLsgqsF6FGaq3Z4ERww= +PresharedKeyFile = /etc/ansible_secrets/wireguard_wg55_peer_dario_psk + +[WireGuardPeer] +# friendly_name = June-mobile +AllowedIPs = 10.89.214.11/32,2a07:c481:1:37::11/128 +PublicKey = 6edjXykegUgGjbkIG1aJyBlX1SgTKcqXXaSBVPHdKDc= +PresharedKeyFile = /etc/ansible_secrets/wireguard_wg55_peer_June-mobile_psk + +[WireGuardPeer] +# friendly_name = djerun_at_ferrum.local +AllowedIPs = 10.89.214.12/32,2a07:c481:1:37::12/128 +PublicKey = aHbdkTHhPkd+o7wWfTua9nd72aF4OVp66zGtpaoD8Fg= + +[WireGuardPeer] +# friendly_name = c6ristian +AllowedIPs = 10.89.214.13/32,2a07:c481:1:37::13/128 +PublicKey = 6ndwj3Ur6AqfUPWuyPYXIaGZs2ujJKawSQ9LEvlYzEc= +PresharedKeyFile = /etc/ansible_secrets/wireguard_wg55_peer_c6ristian_psk + +[WireGuardPeer] +# friendly_name = langoor +AllowedIPs = 10.89.214.14/32,2a07:c481:1:37::14/128 +PublicKey = qTnVQlQa1m4SucFFNli/xM6QWfsdWx2baRAit7Cg8RM= +PresharedKeyFile = /etc/ansible_secrets/wireguard_wg55_peer_langoor_psk + +[WireGuardPeer] +# friendly_name = langoor_home +AllowedIPs = 10.89.214.15/32,2a07:c481:1:37::15/128 +PublicKey = NeMDs2+5rHuKO5ZYXVUR76GorgdesFUnDOFECQ3RzG4= +PresharedKeyFile = /etc/ansible_secrets/wireguard_wg55_peer_langoor_home_psk + +[WireGuardPeer] +# friendly_name = lilly-lillysLaptop +AllowedIPs = 10.89.214.16/32 #,2a07:c481:1:37::/128 +PublicKey = IBsI+N8qUNpQnDc5HnqQ2Zo/1graFM0RMIecHmAF+Vk= + +[WireGuardPeer] +# friendly_name = bitwhisker +AllowedIPs = 10.89.214.17/32,2a07:c481:1:37::a/128 +PublicKey = DvEGvQPGi+IxeRTIA72Gx3WNINcrV9HRNB1v7mHnhjA= + +[WireGuardPeer] +# friendly_name = forestcat +AllowedIPs = 10.89.214.18/32,2a07:c481:1:37::b/128 +PublicKey = PdJ7KlIeASizj0WTY87d7oSi14/MebrhRa+L8YiPoQE= + diff --git a/resources/z9/rt1/systemd_networkd/20-netlan.network b/resources/z9/rt1/systemd_networkd/20-netlan.network new file mode 100644 index 0000000..3aed715 --- /dev/null +++ b/resources/z9/rt1/systemd_networkd/20-netlan.network @@ -0,0 +1,12 @@ +[Match] +Name=netlan + +[Link] +RequiredForOnline=no + +[Network] +VLAN=netwan.51 +VLAN=netwan.52 +VLAN=netwan.53 +VLAN=netwan.54 + diff --git a/resources/z9/rt1/systemd_networkd/20-netwan.network b/resources/z9/rt1/systemd_networkd/20-netwan.network new file mode 100644 index 0000000..89a8494 --- /dev/null +++ b/resources/z9/rt1/systemd_networkd/20-netwan.network @@ -0,0 +1,9 @@ +[Match] +Name=netwan + +[Link] +RequiredForOnline=no + +[Network] +VLAN=netwan.400 + diff --git a/resources/z9/rt1/systemd_networkd/20-wg55.network b/resources/z9/rt1/systemd_networkd/20-wg55.network new file mode 100644 index 0000000..750e844 --- /dev/null +++ b/resources/z9/rt1/systemd_networkd/20-wg55.network @@ -0,0 +1,6 @@ +[Match] +Name=wg55 + +[Network] +Address=10.89.214.1/24 +Address=2a07:c481:1:37::1/64 diff --git a/resources/z9/rt1/systemd_networkd/21-netlan.51-clients.network b/resources/z9/rt1/systemd_networkd/21-netlan.51-clients.network new file mode 100644 index 0000000..5e9635f --- /dev/null +++ b/resources/z9/rt1/systemd_networkd/21-netlan.51-clients.network @@ -0,0 +1,27 @@ +[Match] +Name=netlan.51 +Type=vlan + +[Link] +RequiredForOnline=no + +[Network] +Description=clients + +# Masquerading done in nftables (nftables.conf). +IPv6SendRA=yes + +[Address] +Address=10.89.208.1/22 + +[IPv6SendRA] +UplinkInterface=netwan.400 +EmitDomains=true +Domains=ccchh.net +Managed=true + +[IPv6Prefix] +Prefix=2a07:c481:1:33::/64 +Assign=true +Token=static:::1 + diff --git a/resources/z9/rt1/systemd_networkd/21-netlan.52-iot.network b/resources/z9/rt1/systemd_networkd/21-netlan.52-iot.network new file mode 100644 index 0000000..5b58610 --- /dev/null +++ b/resources/z9/rt1/systemd_networkd/21-netlan.52-iot.network @@ -0,0 +1,27 @@ +[Match] +Name=netlan.52 +Type=vlan + +[Link] +RequiredForOnline=no + +[Network] +Description=IoT + +# Masquerading done in nftables (nftables.conf). +IPv6SendRA=yes + +[Address] +Address=10.89.212.1/24 + +[IPv6SendRA] +UplinkInterface=netwan.400 +EmitDomains=true +Domains=ccchh.net +Managed=true + +[IPv6Prefix] +Prefix=2a07:c481:1:34::/64 +Assign=true +Token=static:::1 + diff --git a/resources/z9/rt1/systemd_networkd/21-netlan.53-public.network b/resources/z9/rt1/systemd_networkd/21-netlan.53-public.network new file mode 100644 index 0000000..f544a5b --- /dev/null +++ b/resources/z9/rt1/systemd_networkd/21-netlan.53-public.network @@ -0,0 +1,27 @@ +[Match] +Name=netlan.53 +Type=vlan + +[Link] +RequiredForOnline=no + +[Network] +Description=public + +# Masquerading done in nftables (nftables.conf). +IPv6SendRA=yes + +[Address] +Address=185.161.130.65/28 + +[IPv6SendRA] +UplinkInterface=netwan.400 +EmitDomains=true +Domains=ccchh.net +Managed=true + +[IPv6Prefix] +Prefix=2a07:c481:1:35::/64 +Assign=true +Token=static:::1 + diff --git a/resources/z9/rt1/systemd_networkd/21-netlan.54-management.network b/resources/z9/rt1/systemd_networkd/21-netlan.54-management.network new file mode 100644 index 0000000..2396da0 --- /dev/null +++ b/resources/z9/rt1/systemd_networkd/21-netlan.54-management.network @@ -0,0 +1,27 @@ +[Match] +Name=netlan.54 +Type=vlan + +[Link] +RequiredForOnline=no + +[Network] +Description=Management + +# Masquerading done in nftables (nftables.conf). +IPv6SendRA=yes + +[Address] +Address=10.89.213.0/24 + +[IPv6SendRA] +UplinkInterface=netwan.400 +EmitDomains=true +Domains=ccchh.net +Managed=true + +[IPv6Prefix] +Prefix=2a07:c481:1:36::/64 +Assign=true +Token=static:::1 + diff --git a/resources/z9/rt1/systemd_networkd/21-netwan.400-fux_uplink.network b/resources/z9/rt1/systemd_networkd/21-netwan.400-fux_uplink.network new file mode 100644 index 0000000..1657c40 --- /dev/null +++ b/resources/z9/rt1/systemd_networkd/21-netwan.400-fux_uplink.network @@ -0,0 +1,26 @@ +[Match] +Name=netwan.400 +Type=vlan + +[Link] +RequiredForOnline=no + +[Network] +Description=fux-uplink + +DNS=185.161.128.66 +DNS=2a07:c481:0:4::2 +DNS=185.161.128.67 +DNS=2a07:c481:0:4::3 + +IPv6AcceptRA=no +# Masquerading done in nftables (nftables.conf). +IPv6SendRA=no + +[Address] +Address=185.161.129.134/25 +Address=2a07:c481::1:2/64 + +[Route] +Gateway=185.161.129.129 +Gateway=2a07:c481::1 diff --git a/resources/z9/rt1/systemd_networkd_global_config.conf b/resources/z9/rt1/systemd_networkd_global_config.conf new file mode 100644 index 0000000..2d3d8a3 --- /dev/null +++ b/resources/z9/rt1/systemd_networkd_global_config.conf @@ -0,0 +1,3 @@ +[Network] +IPv4Forwarding=true +IPv6Forwarding=true diff --git a/roles/kea_dhcp/defaults/main.yaml b/roles/kea_dhcp/defaults/main.yaml new file mode 100644 index 0000000..409f0a1 --- /dev/null +++ b/roles/kea_dhcp/defaults/main.yaml @@ -0,0 +1,69 @@ +kea_dhcp__stork_agent: + enable: false + prometheus_only: true +kea_dhcp__version_repo: "kea-3-0" +kea_dhcp__dns_servers: + v6: + - "2a07:c481:0:4::2" + - "2a07:c481:0:4::3" + v4: + - "185.161.128.66" + - "185.161.128.67" +kea_dhcp__include_vars: + +kea_dhcp__dhcp4: + enable: false + interfaces: [ ] + control-sockets: + - socket-name: /var/run/kea-dhcp4-ctrl-agent.sock + socket-type: unix + lease-database: + type: memfile + persist: true + option-data: + - name: "domain-name-servers" + code: 6 + csv-format: true + data: "{{ kea_dhcp__dns_servers.v4 | join(',') }}" + subnets: + - id: 0 + subnet: nil + pools: + - pool: nil + reservations: + - ip-address: nil + hostname: beispiel.test + hw-address: "00:11:22:33:44:55" + option-data: + - name: nil, + code: nil, + csv-format: true + data: nil +kea_dhcp__dhcp6: + enable: false + interfaces: [ ] + lease-database: + type: memfile + persist: true + control-sockets: + - socket-name: /var/run/kea-dhcp6-ctrl-agent.sock + socket-type: unix + option-data: + - name: "dns-servers" + code: 23 + csv-format: true + data: "{{ kea_dhcp__dns_servers.v6 | join(',') }}" + subnets: + - id: 0 + subnet: nil + pools: + - pool: nil + reservations: + - ip-address: nil + hostname: beispiel.test + hw-address: "00:11:22:33:44:55" + option-data: + - name: nil, + code: nil, + csv-format: true + data: nil diff --git a/roles/kea_dhcp/handlers/main.yml b/roles/kea_dhcp/handlers/main.yml new file mode 100644 index 0000000..5b44d6e --- /dev/null +++ b/roles/kea_dhcp/handlers/main.yml @@ -0,0 +1,30 @@ +--- +- name: Systemd.daemon_reload + become: true + ansible.builtin.systemd_service: + daemon_reload: true + +- name: Kea_dhcp4.reloaded + ansible.builtin.service: + name: kea-dhcp4 + state: restarted + enabled: true + +- name: Kea_dhcp6.reloaded + ansible.builtin.service: + name: kea-dhcp6 + state: restarted + enabled: true + +- name: Kea_ctrl.reloaded + ansible.builtin.systemd: + name: kea-ctrl-agent + state: restarted + enabled: true + +- name: Stork_agent.restarted + become: true + ansible.builtin.systemd: + name: isc-stork-agent + state: restarted + enabled: true diff --git a/roles/kea_dhcp/meta/argument_specs.yaml b/roles/kea_dhcp/meta/argument_specs.yaml new file mode 100644 index 0000000..995b838 --- /dev/null +++ b/roles/kea_dhcp/meta/argument_specs.yaml @@ -0,0 +1,125 @@ +--- +argument_specs: + main: + short_description: "Role for managing Kea DHCP server" + options: + kea_dhcp__stork_agent: + type: "dict" + description: "Configuration for Stork Agent" + options: + enable: + type: "bool" + default: false + prometheus_only: + type: "bool" + default: true + kea_dhcp__version_repo: + type: "str" + description: "Version of Kea DHCP repository to use" + default: "kea-3-0" + kea_dhcp__dns_servers: + type: "dict" + description: "Default DNS servers for DHCP clients" + options: + v6: + type: "list" + elements: "str" + v4: + type: "list" + elements: "str" + kea_dhcp__dhcp4: + type: "dict" + description: "Configuration for DHCPv4 service" + options: + enable: + type: "bool" + default: false + interfaces: + type: "list" + elements: "str" + default: [] + control-sockets: + type: "list" + elements: "dict" + lease-database: + type: "dict" + option-data: + type: "list" + elements: "dict" + subnets: + type: "list" + elements: "dict" + options: + id: + type: "int" + subnet: + type: "str" + pools: + type: "list" + elements: "dict" + options: + pool: + type: "str" + reservations: + type: "list" + elements: "dict" + options: + ip-address: + type: "str" + hostname: + type: "str" + hw-address: + type: "str" + duid: + type: "str" + option-data: + type: "list" + elements: "dict" + kea_dhcp__dhcp6: + type: "dict" + description: "Configuration for DHCPv6 service" + options: + enable: + type: "bool" + default: false + interfaces: + type: "list" + elements: "str" + default: [] + control-sockets: + type: "list" + elements: "dict" + lease-database: + type: "dict" + option-data: + type: "list" + elements: "dict" + subnets: + type: "list" + elements: "dict" + options: + id: + type: "int" + subnet: + type: "str" + pools: + type: "list" + elements: "dict" + options: + pool: + type: "str" + reservations: + type: "list" + elements: "dict" + options: + ip-address: + type: "str" + hostname: + type: "str" + hw-address: + type: "str" + duid: + type: "str" + option-data: + type: "list" + elements: "dict" diff --git a/roles/kea_dhcp/tasks/install_archlinux.yml b/roles/kea_dhcp/tasks/install_archlinux.yml new file mode 100644 index 0000000..7bdb140 --- /dev/null +++ b/roles/kea_dhcp/tasks/install_archlinux.yml @@ -0,0 +1,8 @@ +--- +- name: Install Kea on Archlinux + when: ansible_facts['distribution'] == "Archlinux" + become: true + community.general.pacman: + name: kea + state: present + update_cache: false diff --git a/roles/kea_dhcp/tasks/install_debian.yml b/roles/kea_dhcp/tasks/install_debian.yml new file mode 100644 index 0000000..2ac2346 --- /dev/null +++ b/roles/kea_dhcp/tasks/install_debian.yml @@ -0,0 +1,22 @@ +--- +- name: Register isc-kea apt repository + become: true + register: kea_dhcp_repo + when: ansible_facts['distribution'] == "Debian" + ansible.builtin.deb822_repository: + name: "isc-{{ kea_dhcp__version_repo }}" + uris: "https://dl.cloudsmith.io/public/isc/{{ kea_dhcp__version_repo }}/deb/debian" + suites: any-version + components: main + signed_by: "https://dl.cloudsmith.io/public/isc/{{ kea_dhcp__version_repo }}/gpg.key" + +- name: Install Kea packages + become: true + when: ansible_facts['distribution'] == "Debian" + ansible.builtin.apt: + name: + - isc-kea-dhcp4 + - isc-kea-dhcp6 + - isc-kea-ctrl-agent + - isc-kea-admin + update_cache: "{{ kea_dhcp_install_repo.changed }}" diff --git a/roles/kea_dhcp/tasks/kea.yaml b/roles/kea_dhcp/tasks/kea.yaml new file mode 100644 index 0000000..a4fd3b5 --- /dev/null +++ b/roles/kea_dhcp/tasks/kea.yaml @@ -0,0 +1,51 @@ +--- +- name: Include config vars + tags: [ kea, include_vars ] + when: kea_dhcp__include_vars is not None + ansible.builtin.include_vars: + file: "{{ kea_dhcp__include_vars }}" + +- name: Deploy kea-dhcp4 configuration file + tags: [ kea, dhcp4 ] + become: true + when: kea_dhcp__dhcp4.enable + ansible.builtin.template: + src: kea-dhcp4.conf.jinja + dest: /etc/kea/kea-dhcp4.conf + backup: true + owner: root + group: kea + mode: "u=rw,g=r,o=" + validate: kea-dhcp4 -T %s + notify: + - Kea_dhcp4.reloaded + +- name: Deploy kea-dhcp6 configuration file + tags: [ kea, dhcp6 ] + become: true + when: kea_dhcp__dhcp6.enable + ansible.builtin.template: + src: kea-dhcp6.conf.jinja + dest: /etc/kea/kea-dhcp6.conf + backup: true + owner: root + group: kea + mode: "u=rw,g=r,o=" + validate: kea-dhcp6 -T %s + notify: + - Kea_dhcp6.reloaded + +- name: Copy kea-ctrl-agent configuration file + tags: [ kea, ctrl-agent ] + become: true + when: kea_dhcp__stork_agent.enable + ansible.builtin.template: + src: kea-ctrl-agent.conf.j2 + dest: /etc/kea/kea-ctrl-agent.conf + owner: root + group: kea + mode: "u=rw,g=r,o=" + validate: kea-ctrl-agent -t %s + notify: + - Kea_ctrl.reloaded + - Stork_agent.restarted diff --git a/roles/kea_dhcp/tasks/main.yml b/roles/kea_dhcp/tasks/main.yml new file mode 100644 index 0000000..a3478fa --- /dev/null +++ b/roles/kea_dhcp/tasks/main.yml @@ -0,0 +1,19 @@ +--- +- name: Setup Kea DHCP + tags: [kea, dhcp] + block: + - name: Install Kea on Archlinux + when: ansible_facts['distribution'] == "Archlinux" + ansible.builtin.import_tasks: install_archlinux.yml + + - name: Install Kea on Debian + when: ansible_facts['distribution'] == "Debian" + ansible.builtin.import_tasks: install_debian.yml + + - name: Configure Kea + ansible.builtin.include_tasks: kea.yaml + +- name: Run stork-agent tasks + tags: [stork-agent, monitoring] + when: kea_dhcp__stork_agent.enable + ansible.builtin.include_tasks: stork-agent.yaml diff --git a/roles/kea_dhcp/tasks/stork-agent.yaml b/roles/kea_dhcp/tasks/stork-agent.yaml new file mode 100644 index 0000000..916760c --- /dev/null +++ b/roles/kea_dhcp/tasks/stork-agent.yaml @@ -0,0 +1,76 @@ +--- +- name: Install stork-agent + tags: [stork-agent] + block: + - name: Install stork-agent on Archlinux + when: ansible_facts['distribution'] == "Archlinux" + tags: [stork-agent, archlinux] + block: + - name: Create stork-agent user + ansible.builtin.user: + name: stork-agent + create_home: false + home: "/var/lib/stork-agent" + shell: "/usr/bin/nologin" + system: true + groups: ["kea"] + append: true + + - name: Install stork-agent with aur_pkg_install + ansible.builtin.include_role: + name: aur_pkg_install + vars: + aur_pkg_install__pkg_name: "stork-agent" + aur_pkg_install__git_clone_url: "https://ansible:{{ secret__ansible_git_token }}@git.fux-eg.net/aur-mirror/stork-agent.git" + aur_pkg_install__git_ref: "bf96e34" + + - name: Install stork-agent on Debian + when: ansible_facts['distribution'] == "Debian" + tags: [stork-agent, debian] + block: + - name: Register isc-stork apt repository + become: true + register: "kea_dhcp_install_repo" + ansible.builtin.deb822_repository: + name: isc-stork + uris: https://dl.cloudsmith.io/public/isc/stork/deb/debian + suites: any-version + components: main + signed_by: https://dl.cloudsmith.io/public/isc/stork/gpg.key + + - name: Install isc-stork-agent + become: true + ansible.builtin.apt: + name: isc-stork-agent + update_cache: "{{ kea_dhcp_install_repo.changed }}" + + - name: Add stork-agent user to _kea group on Debian + when: ansible_facts['distribution'] == "Debian" + become: true + ansible.builtin.user: + name: stork-agent + groups: ["_kea"] + append: true + + - name: Config for stork-agent + ansible.builtin.template: + src: stork-agent.env.jinja + dest: /etc/stork/agent.env + owner: root + group: root + mode: "0660" + notify: + - Systemd_daemon_reload + - Stork_agent.restarted + + - name: Flush handlers + ansible.builtin.meta: flush_handlers + + - name: Ensure that stork kea exporter is working + ansible.builtin.uri: + url: "http://localhost:9547/metrics" + method: GET + register: kea_dhcp_stork_status_code + retries: 6 + delay: 5 + until: kea_dhcp_stork_status_code.status == 200 diff --git a/roles/kea_dhcp/templates/kea-ctrl-agent.conf.j2 b/roles/kea_dhcp/templates/kea-ctrl-agent.conf.j2 new file mode 100644 index 0000000..5ac1473 --- /dev/null +++ b/roles/kea_dhcp/templates/kea-ctrl-agent.conf.j2 @@ -0,0 +1,20 @@ +{ +"Control-agent": { + "http-host": "127.0.0.1", + "http-port": 8000, + "control-sockets": { + {% if kea_dhcp__dhcp4.enable | default(false) %} + "dhcp4": { + "socket-type": "{{ kea_dhcp__dhcp4['control-sockets'][0]['socket-type'] }}", + "socket-name": "{{ kea_dhcp__dhcp4['control-sockets'][0]['socket-name'] }}" + }{% if kea_dhcp__dhcp6.enable %},{% endif %} + {% endif %} + {% if kea_dhcp__dhcp6.enable | default(false) %} + "dhcp6": { + "socket-type": "{{ kea_dhcp__dhcp6['control-sockets'][0]['socket-type'] }}", + "socket-name": "{{ kea_dhcp__dhcp6['control-sockets'][0]['socket-name'] }}" + }, + {% endif %} + } +} +} diff --git a/roles/kea_dhcp/templates/kea-dhcp4.conf.jinja b/roles/kea_dhcp/templates/kea-dhcp4.conf.jinja new file mode 100644 index 0000000..78f06ae --- /dev/null +++ b/roles/kea_dhcp/templates/kea-dhcp4.conf.jinja @@ -0,0 +1,27 @@ +{ + "Dhcp4": { + "interfaces-config": { + "interfaces": {{ kea_dhcp__dhcp4.interfaces | to_nice_json }} + }, + "control-sockets": {{ kea_dhcp__dhcp4['control-sockets'] | to_nice_json }}, + "lease-database": {{ kea_dhcp__dhcp4['lease-database'] | to_nice_json }}, + {% if kea_dhcp__dhcp4['option-data'] is defined and kea_dhcp__dhcp4['option-data'] %} + "option-data": {{ kea_dhcp__dhcp4['option-data'] | to_nice_json }}, + {% endif %} + "subnet4": [ + {% for subnet in kea_dhcp__dhcp4.subnets %} + { + "id": {{ subnet.id }}, + "subnet": "{{ subnet.subnet }}", + "pools": {{ subnet.pools | to_nice_json }}, + {% if subnet.reservations is defined and subnet.reservations %} + "reservations": {{ subnet.reservations | to_nice_json }}, + {% endif %} + {% if subnet['option-data'] is defined and subnet['option-data'] %} + "option-data": {{ subnet['option-data'] | to_nice_json }} + {% endif %} + }{% if not loop.last %},{% endif %} + {% endfor %} + ] + } +} diff --git a/roles/kea_dhcp/templates/kea-dhcp6.conf.jinja b/roles/kea_dhcp/templates/kea-dhcp6.conf.jinja new file mode 100644 index 0000000..da1929a --- /dev/null +++ b/roles/kea_dhcp/templates/kea-dhcp6.conf.jinja @@ -0,0 +1,27 @@ +{ + "Dhcp6": { + "interfaces-config": { + "interfaces": {{ kea_dhcp__dhcp6.interfaces | to_nice_json }} + }, + "control-sockets": {{ kea_dhcp__dhcp6['control-sockets'] | to_nice_json }}, + "lease-database": {{ kea_dhcp__dhcp6['lease-database'] | to_nice_json }}, + {% if kea_dhcp__dhcp6['option-data'] is defined and kea_dhcp__dhcp6['option-data'] %} + "option-data": {{ kea_dhcp__dhcp6['option-data'] | to_nice_json }}, + {% endif %} + "subnet6": [ + {% for subnet in kea_dhcp__dhcp6.subnets %} + { + "id": {{ subnet.id }}, + "subnet": "{{ subnet.subnet }}", + "pools": {{ subnet.pools | to_nice_json }}, + {% if subnet.reservations is defined and subnet.reservations %} + "reservations": {{ subnet.reservations | to_nice_json }}, + {% endif %} + {% if subnet['option-data'] is defined and subnet['option-data'] %} + "option-data": {{ subnet['option-data'] | to_nice_json }} + {% endif %} + }{% if not loop.last %},{% endif %} + {% endfor %} + ] + } +} diff --git a/roles/kea_dhcp/templates/stork-agent.env.jinja b/roles/kea_dhcp/templates/stork-agent.env.jinja new file mode 100644 index 0000000..bdfa4d2 --- /dev/null +++ b/roles/kea_dhcp/templates/stork-agent.env.jinja @@ -0,0 +1,44 @@ +### the IP or hostname to listen on for incoming Stork server connections +# STORK_AGENT_HOST= + +### the TCP port to listen on for incoming Stork server connections +# STORK_AGENT_PORT=8081 + +### listen for commands from the Stork server only, but not for Prometheus requests +# STORK_AGENT_LISTEN_STORK_ONLY=true + +{% if kea_dhcp__stork_agent.prometheus_only %} +### listen for Prometheus requests only, but not for commands from the Stork server +STORK_AGENT_LISTEN_PROMETHEUS_ONLY=true +{% endif %} + +### settings for exporting stats to Prometheus +### the IP or hostname on which the agent exports Kea statistics to Prometheus +# STORK_AGENT_PROMETHEUS_KEA_EXPORTER_ADDRESS= +### the port on which the agent exports Kea statistics to Prometheus +# STORK_AGENT_PROMETHEUS_KEA_EXPORTER_PORT= +## enable or disable collecting per-subnet stats from Kea +# STORK_AGENT_PROMETHEUS_KEA_EXPORTER_PER_SUBNET_STATS=true +### the IP or hostname on which the agent exports BIND 9 statistics to Prometheus +# STORK_AGENT_PROMETHEUS_BIND9_EXPORTER_ADDRESS= +### the port on which the agent exports BIND 9 statistics to Prometheus +# STORK_AGENT_PROMETHEUS_BIND9_EXPORTER_PORT= + +### Stork Server URL used by the agent to send REST commands to the server during agent registration +# STORK_AGENT_SERVER_URL= + +### skip TLS certificate verification when the Stork Agent connects +### to Kea over TLS and Kea uses self-signed certificates +# STORK_AGENT_SKIP_TLS_CERT_VERIFICATION=true + + +### Logging parameters + +### Set logging level. Supported values are: DEBUG, INFO, WARN, ERROR +STORK_LOG_LEVEL=DEBUG +### disable output colorization +# CLICOLOR=false + +### path to the hook directory +# STORK_AGENT_HOOK_DIRECTORY= + diff --git a/roles/unbound/README.md b/roles/unbound/README.md new file mode 100644 index 0000000..806b9d8 --- /dev/null +++ b/roles/unbound/README.md @@ -0,0 +1,19 @@ +# Unbound DNS resolver + +Role fora a validating, recursive, caching DNS resolver based on [Unbound](https://nlnetlabs.nl/projects/unbound/about/). +It is designed to be fast and lean and incorporates modern features based on open standards. + +- [Documentation](https://unbound.docs.nlnetlabs.nl/en/latest/) + +## Role Customization + +The following variables can be used to customize this role: + +| Variable | Type | Default | Description | +|------------------------------------------|-----------------|-----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| unbound_install_prometheus_exporter | Boolean | `true` | Whether [Unbound Exporter](https://github.com/letsencrypt/unbound_exporter) should also be installed to expose resolver statistics in prometheus format. | +| unbound_bind_interfaces | List of Strings | `[0.0.0.0, ::]` | List of interface names or IP addresses on which unbound will listen for dns queries | +| unbound_enable_unbound_control | Boolean | `true` | Whether the [remote control](https://unbound.docs.nlnetlabs.nl/en/latest/getting-started/configuration.html#set-up-remote-control) feature of unbound should be configured. | +| unbound_enable_dnssec | Boolean | `true` | Whether dnssec validation should be enabled | +| unbound_access_control | List of Strings | `[]` | **Required** List of [unbound access control values](https://unbound.docs.nlnetlabs.nl/en/latest/manpages/unbound.conf.html#:~:text=access-control:%20%3CIP%20netblock%3E%20%3Caction%3E) | +| unbound_disable_systemd_networkd | Boolean | `true` | If true, systemd-networkd is disabled and the local system is pointed towards the configured dns resolver. | diff --git a/roles/unbound/defaults/main.yml b/roles/unbound/defaults/main.yml new file mode 100644 index 0000000..fa6cb24 --- /dev/null +++ b/roles/unbound/defaults/main.yml @@ -0,0 +1,7 @@ +unbound_install_prometheus_exporter: true +unbound_bind_interfaces: [ "0.0.0.0", "::" ] +unbound_disable_systemd_networkd: true +unbound_enable_unbound_control: true +unbound_enable_dnssec: true +unbound_access_control: [ ] +unbound_private_domain: [ ] diff --git a/roles/unbound/files/no-resolved.resolv.conf b/roles/unbound/files/no-resolved.resolv.conf new file mode 100644 index 0000000..bbc8559 --- /dev/null +++ b/roles/unbound/files/no-resolved.resolv.conf @@ -0,0 +1 @@ +nameserver 127.0.0.1 diff --git a/roles/unbound/handlers/main.yml b/roles/unbound/handlers/main.yml new file mode 100644 index 0000000..e1345bf --- /dev/null +++ b/roles/unbound/handlers/main.yml @@ -0,0 +1,27 @@ +- name: unbound.restarted + tags: [ unbound, dns, dns_resolver ] + become: true + ansible.builtin.systemd: + name: unbound.service + state: restarted + +- name: unbound.reloaded + tags: [ unbound, dns, dns_resolver ] + become: true + ansible.builtin.systemd: + name: unbound.service + state: reloaded + +- name: prometheus-unbound-exporter.restarted + become: true + ansible.builtin.systemd: + name: prometheus-unbound-exporter.service + state: restarted + enabled: true + +- name: prometheus-unbound-exporter.enabled + become: true + ansible.builtin.systemd: + name: prometheus-unbound-exporter.service + enabled: true + daemon_reload: true diff --git a/roles/unbound/tasks/main.yml b/roles/unbound/tasks/main.yml new file mode 100644 index 0000000..7ed42cb --- /dev/null +++ b/roles/unbound/tasks/main.yml @@ -0,0 +1,63 @@ +- name: unbound role main + tags: [ unbound, dns, dns_resolver ] + block: + + - name: install unbound dns resolver + become: true + ansible.builtin.package: + name: unbound + + - name: install extra dns tooling + become: true + ansible.builtin.package: + name: [ bind ] # the bind package includes tools like dig in archlinux + + - name: ensure correct directory permissions + become: true + ansible.builtin.file: + path: /etc/unbound + state: directory + mode: u=rwX,g=rX,o=rX + recurse: true + owner: unbound + group: unbound + + - name: configure unbound dns resolver + become: true + notify: unbound.restarted + ansible.builtin.template: + src: unbound.conf.j2 + dest: /etc/unbound/unbound.conf + owner: unbound + group: unbound + mode: u=rw,g=r,o=r + + - name: ensure unbound is running and enabled + become: true + ansible.builtin.systemd: + name: unbound.service + state: started + enabled: true + + - name: disable systemd-resolved + become: true + when: unbound_disable_systemd_networkd + ansible.builtin.systemd: + name: systemd-resolved.service + state: stopped + enabled: false + + - name: configure system resolver to point to local unbound + become: true + when: unbound_disable_systemd_networkd + ansible.builtin.copy: + src: no-resolved.resolv.conf + dest: /etc/resolv.conf + owner: unbound + group: unbound + mode: u=rw,g=r,o=r + + + - name: install and configure prometheus-exporter for unbound + ansible.builtin.import_tasks: prometheus-exporter.yml + when: unbound_install_prometheus_exporter diff --git a/roles/unbound/tasks/prometheus-exporter.yml b/roles/unbound/tasks/prometheus-exporter.yml new file mode 100644 index 0000000..d05b838 --- /dev/null +++ b/roles/unbound/tasks/prometheus-exporter.yml @@ -0,0 +1,17 @@ +--- +- name: install unbound prometheus exporter + become: true + ansible.builtin.package: + name: prometheus-unbound-exporter + notify: prometheus-unbound-exporter.enabled + +- name: configure unbound exporter + become: true + ansible.builtin.copy: + dest: /etc/conf.d/prometheus-unbound-exporter + content: | + UNBOUND_EXPORTER_ARGS="-unbound.ca "" -unbound.cert "" -unbound.host "unix:///run/unbound-control.sock" + owner: root + group: root + mode: '0660' + notify: prometheus-unbound-exporter.restarted diff --git a/roles/unbound/templates/unbound.conf.j2 b/roles/unbound/templates/unbound.conf.j2 new file mode 100644 index 0000000..a1e310e --- /dev/null +++ b/roles/unbound/templates/unbound.conf.j2 @@ -0,0 +1,73 @@ +# ref: https://unbound.docs.nlnetlabs.nl/en/latest/manpages/unbound.conf.html +# unbound.conf(5) man page +server: + {% if unbound_enable_dnssec -%} + # disable chroot because unbound is the only thing running on the VM + # and because it has issues with how archlinux configures the systemd units write protection regarding the anchor file + chroot: "" + + # location of the trust anchor file that enables DNSSEC + # this file is generated by the `unbound-anchor` command + auto-trust-anchor-file: "/etc/unbound/trusted-key.key" + {% endif -%} + + # use all CPUs + num-threads: 2 + + # more cache memory + rrset-cache-size: 60m + msg-cache-size: 30m + + # prefetch to keep the cache up to date + prefetch: yes + + # fetch the DNSKEYs earlier in the validation process, when a DS record is encountered + prefetch-key: yes + + # Faster UDP with multithreading (only on Linux). + so-reuseport: yes + + # disable special large send buffer handling and just use kernel defaults + so-sndbuf: 0 + + # send minimal amount of information to upstream servers to enhance privacy + qname-minimisation: yes + + # specify the interface to answer queries from by ip-address. + {% for i in unbound_bind_interfaces -%} + interface: "{{ i }}" + {% endfor %} + + # addresses from the IP range that are allowed to connect to the resolver + {% for i in unbound_access_control -%} + access-control: {{ i }} + {% endfor -%} + + {% for i in unbound_private_domain -%} + private-domain: {{ i }} + {% endfor -%} + + # The number of seconds between printing statistics to the log for every thread. + statistics-interval: 0 + + # Extended statistics are printed, Keeping track of more statistics takes time. + extended-statistics: yes + +remote-control: + control-enable: {{ "yes" if unbound_enable_unbound_control else "no" }} + control-interface: /run/unbound-control.sock + + +# configure some zones for which this resolver will act authoritatively +# https://www.dns.icann.org/services/axfr/ +{% for i in [ ".", "in-addr.arpa.", "arpa.", "root-servers.net.", "ip6.arpa.", "ip6-servers.arpa.", "mcast.net." ] %} +auth-zone: + name: "{{ i }}" + primary: "lax.xfr.dns.icann.org" + primary: "iad.xfr.dns.icann.org" + fallback-enabled: yes + for-downstream: no + for-upstream: yes + + +{% endfor %}