Compare commits

..

7 commits

115 changed files with 2440 additions and 4714 deletions

View file

@ -1,59 +0,0 @@
name: Build_Deploy
on:
workflow_run:
workflows: [ "Update_Flake" ]
types:
- completed
push:
branches:
- 'main'
paths:
- applications/**/*
- machines/**/*
- secrets/**/*
- flake.*
- config/**/*
- .forgejo/**/*
jobs:
linter:
runs-on: nix
steps:
- uses: actions/checkout@v4
- run: nix fmt -- --check .
- run: nix --version
#if: github.repository == 'Skynet/nixos'
build:
runs-on: nix
steps:
- uses: actions/checkout@v4
- run: nix develop -v
# - name: Archive Test Results
# if: always()
# run: sleep 100m
# - run: colmena build -v --on @active-dns
# - run: colmena build -v --on @active-core
# - run: colmena build -v --on @active
# - run: colmena build -v --on @active-ext
# - run: colmena build -v --on @active-git
deploy_dns:
runs-on: nix
needs: [ linter, build ]
steps:
- uses: actions/checkout@v4
- run: colmena apply -v --on @active-dns --show-trace
shell: bash
deploy_active:
strategy:
matrix:
batch: [ active-core, active, active-ext ]
runs-on: nix
needs: [ deploy_dns ]
steps:
- uses: actions/checkout@v4
- run: colmena apply -v --on @${{ matrix.batch }} --show-trace
shell: bash

View file

@ -1,12 +0,0 @@
name: Update_Forgejo
on:
workflow_dispatch:
jobs:
deploy:
runs-on: nix
steps:
- uses: actions/checkout@v4
- run: colmena apply -v --on @active-git --show-trace
shell: bash

View file

@ -1,31 +0,0 @@
name: Update_Flake
run-name: "[Update Flake] ${{ inputs.input_to_update }}"
on:
workflow_dispatch:
inputs:
input_to_update:
description: 'Flake input to update'
required: false
type: string
jobs:
update:
runs-on: nix
permissions:
# Give the default GITHUB_TOKEN write permission to commit and push the
# added or changed files to the repository.
contents: write
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
token: ${{ secrets.PIPELINE_TOKEN }}
- run: nix flake update ${{ inputs.input_to_update }}
shell: bash
- uses: https://github.com/stefanzweifel/git-auto-commit-action@v5
with:
commit_message: "Updated flake for ${{ inputs.input_to_update }}"

View file

@ -1,41 +0,0 @@
# The websites can sometimes cause issues when being built and deployed
# This pipeline is to update the inputs from the server
name: Update_Flake_Websites
run-name: "[Update Flake Websites]"
on:
workflow_dispatch:
jobs:
update:
runs-on: nix
permissions:
# Give the default GITHUB_TOKEN write permission to commit and push the
# added or changed files to the repository.
contents: write
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
token: ${{ secrets.PIPELINE_TOKEN }}
- run: nix flake update skynet_website_2003
shell: bash
- run: nix flake update skynet_website_2006
shell: bash
- run: nix flake update skynet_website_2016
shell: bash
- run: nix flake update skynet_website_2021
shell: bash
- run: nix flake update skynet_website_2023
shell: bash
- run: nix flake update skynet_website_2024
shell: bash
- run: nix flake update skynet_website
shell: bash
- uses: https://github.com/stefanzweifel/git-auto-commit-action@v5
with:
commit_message: "Updated flake for Websites"

3
.gitignore vendored
View file

@ -6,9 +6,6 @@
*.tmp *.tmp
tmp tmp
# open office tmp lockfiles
.~lock.*
# Test files # Test files
test.* test.*
*.test.* *.test.*

View file

@ -30,7 +30,7 @@ update:
# the part that updates the flake # the part that updates the flake
- nix --experimental-features 'nix-command flakes' flake lock --update-input $PACKAGE_NAME - nix --experimental-features 'nix-command flakes' flake lock --update-input $PACKAGE_NAME
- git add flake.lock - git add flake.lock
- git commit -m "Updated flake for $PACKAGE_NAME" || echo "No changes, nothing to commit" - git commit -m "[skip ci] Updated flake for $PACKAGE_NAME" || echo "No changes, nothing to commit"
# we have a custom domain # we have a custom domain
- git remote rm origin && git remote add origin ssh://git@gitlab.skynet.ie:2222/compsoc1/skynet/nixos.git - git remote rm origin && git remote add origin ssh://git@gitlab.skynet.ie:2222/compsoc1/skynet/nixos.git
- git push origin HEAD:$CI_COMMIT_REF_NAME - git push origin HEAD:$CI_COMMIT_REF_NAME
@ -48,14 +48,13 @@ sync_repos:
- chmod +x ./sync.sh - chmod +x ./sync.sh
- ./sync.sh - ./sync.sh
rules: rules:
- if: $UPDATE_FLAKE == "yes" - if: '$SYNC_OVERRIDE == "true"'
when: never - changes:
- if: '$CI_PROJECT_NAMESPACE == "compsoc1/skynet" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
changes:
- sync/repos.csv - sync/repos.csv
.scripts_base: &scripts_base .scripts_base: &scripts_base
# load nix environment # load nix environment
- git pull origin $CI_COMMIT_REF_NAME
- . "$HOME/.nix-profile/etc/profile.d/nix.sh" - . "$HOME/.nix-profile/etc/profile.d/nix.sh"
- nix --extra-experimental-features 'nix-command flakes' profile install nixpkgs#colmena - nix --extra-experimental-features 'nix-command flakes' profile install nixpkgs#colmena
@ -66,23 +65,13 @@ sync_repos:
- mkdir -p ~/.ssh - mkdir -p ~/.ssh
- chmod 700 ~/.ssh - chmod 700 ~/.ssh
.scripts_cache: &scripts_cache
- nix --extra-experimental-features 'nix-command flakes' profile install nixpkgs#attic-client
- attic login skynet https://nix-cache.skynet.ie/ $CACHE_KEY
- attic use skynet-cache
# add any new items to the cache
- attic watch-store skynet-cache &
# every commit on main will build and deploy # every commit on main will build and deploy
.build_template: &builder .build_template: &builder
tags: tags:
- nix - nix
before_script: before_script:
- *scripts_base - *scripts_base
- *scripts_cache
rules: rules:
- if: $UPDATE_FLAKE == "yes"
when: never
- changes: - changes:
- applications/**/* - applications/**/*
- machines/**/* - machines/**/*
@ -96,10 +85,7 @@ sync_repos:
before_script: before_script:
- *scripts_deploy - *scripts_deploy
- *scripts_base - *scripts_base
- *scripts_cache
rules: rules:
- if: $UPDATE_FLAKE == "yes"
when: never
- if: '$CI_PROJECT_NAMESPACE == "compsoc1/skynet" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' - if: '$CI_PROJECT_NAMESPACE == "compsoc1/skynet" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
changes: changes:
- flake.nix - flake.nix
@ -119,12 +105,11 @@ build:
<<: *builder <<: *builder
stage: test stage: test
script: script:
- nix --extra-experimental-features 'nix-command flakes' develop
- colmena build -v --on @active-dns - colmena build -v --on @active-dns
- colmena build -v --on @active-core - colmena build -v --on @active-core
- colmena build -v --on @active - colmena build -v --on @active
- colmena build -v --on @active-ext - colmena build -v --on @active-ext
- colmena build -v --on @active-git - colmena build -v --on @active-gitlab
# dns always has to be deployed first # dns always has to be deployed first
deploy_dns: deploy_dns:
@ -161,11 +146,12 @@ deploy_ext:
- deploy_dns - deploy_dns
script: script:
- colmena apply -v --on @active-ext - colmena apply -v --on @active-ext
allow_failure: true
deploy_gitlab: deploy_gitlab:
<<: *builder <<: *builder
<<: *deployment <<: *deployment
stage: deploy_gitlab stage: deploy_gitlab
script: script:
- colmena apply -v --on @active-git - colmena apply -v --on @active-gitlab
when: manual when: manual

View file

@ -1,49 +0,0 @@
Rule,Action,Ticket,Status,Source_IP,Source_Server,Destination_IP,Destination_Server,Port_TCP,Port_UDP,Notes
SKYNET_FIREWALL_00000,Add,,Complete,VPN,-,93.1.99.71 - 193.1.99.126,All,22,-,sftp/ssh required from vpn to servers for admins
SKYNET_FIREWALL_00001,Add,,Complete,All,-,193.1.99.109,SKYNET00004,-,53,Nameserver for skynet.ie
SKYNET_FIREWALL_00002,Add,,Complete,All,-,193.1.99.111,SKYNET00005,"80, 443, 8000",-,"ULFM, http(s) for internet streaming, 8000 for connecting to the server."
SKYNET_FIREWALL_00003,Add,,Complete,All,-,193.1.99.112,SKYNET00006,"80, 443, 25565",-,"Games host, Minecraft uses 25565 (will have more ports in the future)"
SKYNET_FIREWALL_00004,Add,,Complete,All,-,193.1.99.120,SKYNET00002,-,53,Nameserver for skynet.ie
SKYNET_FIREWALL_00005,Add,i23-01-19_681,Complete,193.1.99.72,SKYNET00001,All,-,-,-,Allow outbound access
SKYNET_FIREWALL_00006,Add,i23-01-19_681,Complete,193.1.99.75,SKYNET00008,All,-,-,-,Allow outbound access
SKYNET_FIREWALL_00007,Add,i23-01-19_681,Complete,193.1.99.109,SKYNET00004,All,-,-,-,Allow outbound access
SKYNET_FIREWALL_00008,Add,i23-01-19_681,Complete,193.1.99.111,SKYNET00005,All,-,-,-,Allow outbound access
SKYNET_FIREWALL_00009,Add,i23-01-19_681,Complete,193.1.99.112,SKYNET00006,All,-,-,-,Allow outbound access
SKYNET_FIREWALL_00010,Add,i23-01-19_681,Complete,193.1.99.120,SKYNET00002,All,-,-,-,Allow outbound access
SKYNET_FIREWALL_00011,Add,i23-05-18_249,Complete,All,-,193.1.99.75,SKYNET00008,"80, 443",-,For gitlab Access
SKYNET_FIREWALL_00012,Add,i23-05-18_249,Complete,193.1.99.72 - 193.1.99.126,-,All,-,-,-,"I would also like to extend the outbound access to cover our entire range (193.1.99.72 to 193.1.99.126) to allow for setup for more servers on those ip's (need to download updates and packages).
I have a few servers I plan to setup over the next two weeks, one after another as the later ones depend on earlier ones.
In such a case asking for permission for each individual IP would induce several tickets and a few weeks of paperwork going through change control.
Only a few of these sevices will need inbound ports opened on ITD's firewall, which can be requested when the systems are up, running and secured."
SKYNET_FIREWALL_00013,Add,i23-05-18_249,Complete,All,-,193.1.99.76,SKYNET00009,"143, 993, 587, 465",-,Email Server
SKYNET_FIREWALL_00014,Add,i23-06-19_525,Complete,All,-,193.1.99.76,SKYNET00009,"80, 443, 25",-,"Mailserver here, SPF, DKIM and DMARC are all set up"
SKYNET_FIREWALL_00015,Add,i23-06-19_525,Complete,All,-,193.1.99.79,SKYNET00011,"80, 443",-,Main Skynet webserver
SKYNET_FIREWALL_00016,Add,i23-06-30_024,Complete,All,-,193.1.96.165,SKYNET00012,22,-,"Skynet user's server
Outlet is 131 or 132"
SKYNET_FIREWALL_00017,Add,i23-06-30_024,Complete,193.1.96.165,SKYNET00012,193.1.99.120,SKYNET00002,-,53,Allow Skynet server to use our own internal DNS
SKYNET_FIREWALL_00018,Add,i23-06-30_024,Complete,193.1.96.165,SKYNET00012,193.1.99.74,SKYNET00007,389/636,-,Allow Skynet server to access LDAP
,Add,i23-07-28_010,Denied,All,-,193.1.99.74,SKYNET00007,"80, 443",-,Self Service site for Skynet accounts Only 443 on account modification pages
SKYNET_FIREWALL_00019,Add,i23-07-28_010,Complete,All,-,193.1.99.74,SKYNET00007,443,-,Self Service site for Skynet accounts
SKYNET_FIREWALL_00020,Add,i23-09-05_639,Complete,All,-,193.1.96.165,SKYNET00012,"80, 443",-,Web hosting for user sites
SKYNET_FIREWALL_00021,Add,i23-10-27_014,Complete,All,-,193.1.99.77,SKYNET00014,"80, 443",-,"Nextcloud, selfhosted google services, filestorage and documents"
SKYNET_FIREWALL_00022,Add,i24-02-01_102,Complete,193.1.96.165,SKYNET00012,103.1.99.109,SKYNET00004,-,53,Give the Skynet server access to ur secondary DNS
SKYNET_FIREWALL_00023,Add,i24-02-01_102,Complete,193.1.99.78,SKYNET00010,193.1.96.165,SKYNET00012,22,-,Allow our gitlab runner to access and deploy to teh external server
SKYNET_FIREWALL_00024,Add,i24-02-16_065,Complete,All,-,193.1.99.90,SKYNET00016,"80, 443",-,Games Server Administrative panel
SKYNET_FIREWALL_00025,Add,i24-02-16_065,Complete,All,-,193.1.99.91,SKYNET00017,25518-25525,"19132, 24418-24425",Minecraft Games server
SKYNET_FIREWALL_00026,Add,i24-06-04_017,Complete,All,-,193.1.99.76,SKYNET00009,4190,-,"Email sieve to allow members to add email filters to their
skynet mail."
SKYNET_FIREWALL_00027,Add,i24-06-04_017,Complete,All,-,193.1.99.82,SKYNET00018,80/443,-,"Public services such as a binary cache, open governance and keyserver"
,Add,i24-06-04_017,Denied,All,-,193.1.99.90,SKYNET00016,8080,-,"Websocket for admin panel on games management server
Denied because more information on wat it was for was requested"
,Add,i24-06-04_017,Denied,193.1.99.74,SKYNET00007,193.1.96.165,SKYNET00012,9000-9020,-,"Metrics collection, not done because not enough info provided"
SKYNET_FIREWALL_00028,Remove,i24-06-04_017,Complete,-,-,193.1.99.112,SKYNET00019,25565,-,No longer the minecraft game host
SKYNET_FIREWALL_00029,Add,i24-06-04_017,Complete,All,-,193.1.99.90,SKYNET00016,8080,-,Websocket for admin panel on games management server
SKYNET_FIREWALL_00030,Add,i24-06-04_017,Complete,193.1.99.83,SKYNET00020,193.1.96.165,SKYNET00012,9000-9010,-,Metrics Collection
SKYNET_FIREWALL_00031,Add,i24-06-04_017,Complete,All,-,193.1.99.83,SKYNET00020,"80, 443",-,Web interface for Metrics server
SKYNET_FIREWALL_00032,Remove,i24-06-04_017,Complete,All,-,193.1.99.90,SKYNET00016,8080,-,Had incorrectly opened 8080 on the main panel
SKYNET_FIREWALL_00033,Add,i24-06-04_017,Complete,All,-,193.1.99.91,SKYNET00017,8080,-,Websocket for admin panel on games management server
,Add,i24-07-15_112,Denied,193.1.99.75,-,-,-,22,-,Response from ITD - 'Our IT Security team have advised that port 22 and port 2222 are only to be allowed through the VPN and will not be opened to allow inbound ssh connections directly from the internet'
SKYNET_FIREWALL_00034,Add,i25-01-26_075,Complete,All,-,193.1.99.91,SKYNET00017,-,23318-23325,Ports for Minecraft Bedrock on the main games server.
SKYNET_FIREWALL_00035,Add,i25-02-14_114,Complete,193.1.99.75,SKYNET00008,193.1.96.165,SKYNET00012,22,-,Allow our forgejo runner to access and deploy to teh external server
SKYNET_FIREWALL_00036,Add,i25-03-11_125,Complete,All,-,193.1.99.86,SKYNET00027,25,-,Email Filter
SKYNET_FIREWALL_00037,Add,i25-03-30_018,Complete,All,-,193.1.99.91,SKYNET00017,27015/27016/27020,27015/27020,CSGO/TF2 Ports
1 Rule Action Ticket Status Source_IP Source_Server Destination_IP Destination_Server Port_TCP Port_UDP Notes
2 SKYNET_FIREWALL_00000 Add Complete VPN - 93.1.99.71 - 193.1.99.126 All 22 - sftp/ssh required from vpn to servers for admins
3 SKYNET_FIREWALL_00001 Add Complete All - 193.1.99.109 SKYNET00004 - 53 Nameserver for skynet.ie
4 SKYNET_FIREWALL_00002 Add Complete All - 193.1.99.111 SKYNET00005 80, 443, 8000 - ULFM, http(s) for internet streaming, 8000 for connecting to the server.
5 SKYNET_FIREWALL_00003 Add Complete All - 193.1.99.112 SKYNET00006 80, 443, 25565 - Games host, Minecraft uses 25565 (will have more ports in the future)
6 SKYNET_FIREWALL_00004 Add Complete All - 193.1.99.120 SKYNET00002 - 53 Nameserver for skynet.ie
7 SKYNET_FIREWALL_00005 Add i23-01-19_681 Complete 193.1.99.72 SKYNET00001 All - - - Allow outbound access
8 SKYNET_FIREWALL_00006 Add i23-01-19_681 Complete 193.1.99.75 SKYNET00008 All - - - Allow outbound access
9 SKYNET_FIREWALL_00007 Add i23-01-19_681 Complete 193.1.99.109 SKYNET00004 All - - - Allow outbound access
10 SKYNET_FIREWALL_00008 Add i23-01-19_681 Complete 193.1.99.111 SKYNET00005 All - - - Allow outbound access
11 SKYNET_FIREWALL_00009 Add i23-01-19_681 Complete 193.1.99.112 SKYNET00006 All - - - Allow outbound access
12 SKYNET_FIREWALL_00010 Add i23-01-19_681 Complete 193.1.99.120 SKYNET00002 All - - - Allow outbound access
13 SKYNET_FIREWALL_00011 Add i23-05-18_249 Complete All - 193.1.99.75 SKYNET00008 80, 443 - For gitlab Access
14 SKYNET_FIREWALL_00012 Add i23-05-18_249 Complete 193.1.99.72 - 193.1.99.126 - All - - - I would also like to extend the outbound access to cover our entire range (193.1.99.72 to 193.1.99.126) to allow for setup for more servers on those ip's (need to download updates and packages). I have a few servers I plan to setup over the next two weeks, one after another as the later ones depend on earlier ones. In such a case asking for permission for each individual IP would induce several tickets and a few weeks of paperwork going through change control. Only a few of these sevices will need inbound ports opened on ITD's firewall, which can be requested when the systems are up, running and secured.
15 SKYNET_FIREWALL_00013 Add i23-05-18_249 Complete All - 193.1.99.76 SKYNET00009 143, 993, 587, 465 - Email Server
16 SKYNET_FIREWALL_00014 Add i23-06-19_525 Complete All - 193.1.99.76 SKYNET00009 80, 443, 25 - Mailserver here, SPF, DKIM and DMARC are all set up
17 SKYNET_FIREWALL_00015 Add i23-06-19_525 Complete All - 193.1.99.79 SKYNET00011 80, 443 - Main Skynet webserver
18 SKYNET_FIREWALL_00016 Add i23-06-30_024 Complete All - 193.1.96.165 SKYNET00012 22 - Skynet user's server Outlet is 131 or 132
19 SKYNET_FIREWALL_00017 Add i23-06-30_024 Complete 193.1.96.165 SKYNET00012 193.1.99.120 SKYNET00002 - 53 Allow Skynet server to use our own internal DNS
20 SKYNET_FIREWALL_00018 Add i23-06-30_024 Complete 193.1.96.165 SKYNET00012 193.1.99.74 SKYNET00007 389/636 - Allow Skynet server to access LDAP
21 Add i23-07-28_010 Denied All - 193.1.99.74 SKYNET00007 80, 443 - Self Service site for Skynet accounts – Only 443 on account modification pages
22 SKYNET_FIREWALL_00019 Add i23-07-28_010 Complete All - 193.1.99.74 SKYNET00007 443 - Self Service site for Skynet accounts
23 SKYNET_FIREWALL_00020 Add i23-09-05_639 Complete All - 193.1.96.165 SKYNET00012 80, 443 - Web hosting for user sites
24 SKYNET_FIREWALL_00021 Add i23-10-27_014 Complete All - 193.1.99.77 SKYNET00014 80, 443 - Nextcloud, selfhosted google services, filestorage and documents
25 SKYNET_FIREWALL_00022 Add i24-02-01_102 Complete 193.1.96.165 SKYNET00012 103.1.99.109 SKYNET00004 - 53 Give the Skynet server access to ur secondary DNS
26 SKYNET_FIREWALL_00023 Add i24-02-01_102 Complete 193.1.99.78 SKYNET00010 193.1.96.165 SKYNET00012 22 - Allow our gitlab runner to access and deploy to teh external server
27 SKYNET_FIREWALL_00024 Add i24-02-16_065 Complete All - 193.1.99.90 SKYNET00016 80, 443 - Games Server Administrative panel
28 SKYNET_FIREWALL_00025 Add i24-02-16_065 Complete All - 193.1.99.91 SKYNET00017 25518-25525 19132, 24418-24425 Minecraft Games server
29 SKYNET_FIREWALL_00026 Add i24-06-04_017 Complete All - 193.1.99.76 SKYNET00009 4190 - Email sieve to allow members to add email filters to their skynet mail.
30 SKYNET_FIREWALL_00027 Add i24-06-04_017 Complete All - 193.1.99.82 SKYNET00018 80/443 - Public services such as a binary cache, open governance and keyserver
31 Add i24-06-04_017 Denied All - 193.1.99.90 SKYNET00016 8080 - Websocket for admin panel on games management server Denied because more information on wat it was for was requested
32 Add i24-06-04_017 Denied 193.1.99.74 SKYNET00007 193.1.96.165 SKYNET00012 9000-9020 - Metrics collection, not done because not enough info provided
33 SKYNET_FIREWALL_00028 Remove i24-06-04_017 Complete - - 193.1.99.112 SKYNET00019 25565 - No longer the minecraft game host
34 SKYNET_FIREWALL_00029 Add i24-06-04_017 Complete All - 193.1.99.90 SKYNET00016 8080 - Websocket for admin panel on games management server
35 SKYNET_FIREWALL_00030 Add i24-06-04_017 Complete 193.1.99.83 SKYNET00020 193.1.96.165 SKYNET00012 9000-9010 - Metrics Collection
36 SKYNET_FIREWALL_00031 Add i24-06-04_017 Complete All - 193.1.99.83 SKYNET00020 80, 443 - Web interface for Metrics server
37 SKYNET_FIREWALL_00032 Remove i24-06-04_017 Complete All - 193.1.99.90 SKYNET00016 8080 - Had incorrectly opened 8080 on the main panel
38 SKYNET_FIREWALL_00033 Add i24-06-04_017 Complete All - 193.1.99.91 SKYNET00017 8080 - Websocket for admin panel on games management server
39 Add i24-07-15_112 Denied 193.1.99.75 - - - 22 - Response from ITD - 'Our IT Security team have advised that port 22 and port 2222 are only to be allowed through the VPN and will not be opened to allow inbound ssh connections directly from the internet'
40 SKYNET_FIREWALL_00034 Add i25-01-26_075 Complete All - 193.1.99.91 SKYNET00017 - 23318-23325 Ports for Minecraft Bedrock on the main games server.
41 SKYNET_FIREWALL_00035 Add i25-02-14_114 Complete 193.1.99.75 SKYNET00008 193.1.96.165 SKYNET00012 22 - Allow our forgejo runner to access and deploy to teh external server
42 SKYNET_FIREWALL_00036 Add i25-03-11_125 Complete All - 193.1.99.86 SKYNET00027 25 - Email Filter
43 SKYNET_FIREWALL_00037 Add i25-03-30_018 Complete All - 193.1.99.91 SKYNET00017 27015/27016/27020 27015/27020 CSGO/TF2 Ports

View file

@ -1,28 +0,0 @@
Index,Name,Status,IP_Address,OS,Description
SKYNET00001,agentjones,Active,193.1.99.072,Nixos-24.05,Firewall (currently not active)
SKYNET00002,vendetta,Active,193.1.99.120,Nixos-24.05,DNS Nameserver 1
SKYNET00003,jarvis,Active,193.1.99.073,Proxmox,VM Host
SKYNET00004,vigil,Active,193.1.99.109,Nixos-24.05,DNS Nameserver 2
SKYNET00005,galatea,Active,193.1.99.111,Nixos-24.05,ULFM Radio
SKYNET00006,optimus,Retired,193.1.99.112,Nixos-24.05,Retired Games server
SKYNET00007,kitt,Active,193.1.99.074,Nixos-24.05,"LDAP and Self-Service Password/Account management, also hosts our Discord bot"
SKYNET00008,glados,Active,193.1.99.075,Nixos-24.05,Gitlab server
SKYNET00009,gir,Active,193.1.99.076,Nixos-24.05,Email and Webmail
SKYNET00010,wheatly,Active,193.1.99.078,Nixos-24.05,Gitlab Runner
SKYNET00011,earth,Active,193.1.99.079,Nixos-24.05,Offical website host
SKYNET00012,skynet,Active,193.1.96.165,Nixos-24.05,Skynet server. (DMZ)
SKYNET00013,neuromancer,Active,193.1.99.080,Nixos-24.05,Local Backup Server
SKYNET00014,cadie,Active,193.1.99.077,Nixos-24.05,"Services VM, has nextcloud to start with"
SKYNET00015,marvin,Active,193.1.99.081,Nixos-24.05,Trainee testing server
SKYNET00016,optimus,Retired,193.1.99.090,Debian-12,Games server manager (replacing SKYNET00006 soon)
SKYNET00017,bumblebee,Retired,193.1.99.091,Debian-12,Game server - Minecraft
SKYNET00018,calculon,Active,193.1.99.082,Nixos-24.05,"Public Services such as binary cache, Open Governance and Keyserver"
SKYNET00019,deepthought,Active,193.1.99.112,Nixos-24.05,Backup Test Server using restic
SKYNET00020,ariia,Active,193.1.99.083,Nixos-24.05,"Metrics, Grafana and Prometheus"
SKYNET00021,ash,Active,193.1.99.114,NA,Server Room Network access
SKYNET00022,ultron,Active,193.1.99.084,Proxmox,VM Host
SKYNET00023,optimus-test,Retired,193.1.99.085,Nixos,Testing flake for Pelecian
SKYNET00024,optimus,Active,193.1.99.090,Nixos,Games server manager (replaced SKYNET00016)
SKYNET00025,bumblebee,Active,193.1.99.091,Nixos,Game server - Minecraft (replaced SKYNET00017)
SKYNET00026,vision,Active,193.1.99.085,Raspbian,Proxmox Qurom server
SKYNET00027,mimi,Active,193.1.99.086,Proxmox-Mail-Gateway,Proxmox Mail Gateway
1 Index Name Status IP_Address OS Description
2 SKYNET00001 agentjones Active 193.1.99.072 Nixos-24.05 Firewall (currently not active)
3 SKYNET00002 vendetta Active 193.1.99.120 Nixos-24.05 DNS Nameserver 1
4 SKYNET00003 jarvis Active 193.1.99.073 Proxmox VM Host
5 SKYNET00004 vigil Active 193.1.99.109 Nixos-24.05 DNS Nameserver 2
6 SKYNET00005 galatea Active 193.1.99.111 Nixos-24.05 ULFM Radio
7 SKYNET00006 optimus Retired 193.1.99.112 Nixos-24.05 Retired Games server
8 SKYNET00007 kitt Active 193.1.99.074 Nixos-24.05 LDAP and Self-Service Password/Account management, also hosts our Discord bot
9 SKYNET00008 glados Active 193.1.99.075 Nixos-24.05 Gitlab server
10 SKYNET00009 gir Active 193.1.99.076 Nixos-24.05 Email and Webmail
11 SKYNET00010 wheatly Active 193.1.99.078 Nixos-24.05 Gitlab Runner
12 SKYNET00011 earth Active 193.1.99.079 Nixos-24.05 Offical website host
13 SKYNET00012 skynet Active 193.1.96.165 Nixos-24.05 Skynet server. (DMZ)
14 SKYNET00013 neuromancer Active 193.1.99.080 Nixos-24.05 Local Backup Server
15 SKYNET00014 cadie Active 193.1.99.077 Nixos-24.05 Services VM, has nextcloud to start with
16 SKYNET00015 marvin Active 193.1.99.081 Nixos-24.05 Trainee testing server
17 SKYNET00016 optimus Retired 193.1.99.090 Debian-12 Games server manager (replacing SKYNET00006 soon)
18 SKYNET00017 bumblebee Retired 193.1.99.091 Debian-12 Game server - Minecraft
19 SKYNET00018 calculon Active 193.1.99.082 Nixos-24.05 Public Services such as binary cache, Open Governance and Keyserver
20 SKYNET00019 deepthought Active 193.1.99.112 Nixos-24.05 Backup Test Server using restic
21 SKYNET00020 ariia Active 193.1.99.083 Nixos-24.05 Metrics, Grafana and Prometheus
22 SKYNET00021 ash Active 193.1.99.114 NA Server Room Network access
23 SKYNET00022 ultron Active 193.1.99.084 Proxmox VM Host
24 SKYNET00023 optimus-test Retired 193.1.99.085 Nixos Testing flake for Pelecian
25 SKYNET00024 optimus Active 193.1.99.090 Nixos Games server manager (replaced SKYNET00016)
26 SKYNET00025 bumblebee Active 193.1.99.091 Nixos Game server - Minecraft (replaced SKYNET00017)
27 SKYNET00026 vision Active 193.1.99.085 Raspbian Proxmox Qurom server
28 SKYNET00027 mimi Active 193.1.99.086 Proxmox-Mail-Gateway Proxmox Mail Gateway

View file

@ -1,6 +0,0 @@
Index,First Name,Surname,UL Student Email
SKYNET_VPN_ADM_001,Brendan,Golden,12136891@studentmail.ul.ie
SKYNET_VPN_ADM_002,Evan,Cassidy,External
SKYNET_VPN_ADM_003,Eoghan,Conlon,21310262@studentmail.ul.ie
SKYNET_VPN_ADM_004,Eliza,Macovei,23382619@studentmail.ul.ie
SKYNET_VPN_ADM_005,Daragh,Downes,22351159@studentmail.ul.ie
1 Index First Name Surname UL Student Email
2 SKYNET_VPN_ADM_001 Brendan Golden 12136891@studentmail.ul.ie
3 SKYNET_VPN_ADM_002 Evan Cassidy External
4 SKYNET_VPN_ADM_003 Eoghan Conlon 21310262@studentmail.ul.ie
5 SKYNET_VPN_ADM_004 Eliza Macovei 23382619@studentmail.ul.ie
6 SKYNET_VPN_ADM_005 Daragh Downes 22351159@studentmail.ul.ie

View file

@ -1,7 +0,0 @@
Date,Date Modified,Action,Ticket,ID
SKYNET_VPN_ADM_CHANGE_001,2023/04/04,Added,,SKYNET_VPN_ADM_001
SKYNET_VPN_ADM_CHANGE_002,2023/04/04,Added,,SKYNET_VPN_ADM_002
SKYNET_VPN_ADM_CHANGE_003,2023/04/04,Added,,SKYNET_VPN_ADM_003
SKYNET_VPN_ADM_CHANGE_003,2024/07/21,Removed,i24-07-22_760,SKYNET_VPN_ADM_003
SKYNET_VPN_ADM_CHANGE_004,2024/07/21,Added,i24-07-22_760,SKYNET_VPN_ADM_004
SKYNET_VPN_ADM_CHANGE_005,2024/07/21,Added,i24-07-22_760,SKYNET_VPN_ADM_005
1 Date Date Modified Action Ticket ID
2 SKYNET_VPN_ADM_CHANGE_001 2023/04/04 Added SKYNET_VPN_ADM_001
3 SKYNET_VPN_ADM_CHANGE_002 2023/04/04 Added SKYNET_VPN_ADM_002
4 SKYNET_VPN_ADM_CHANGE_003 2023/04/04 Added SKYNET_VPN_ADM_003
5 SKYNET_VPN_ADM_CHANGE_003 2024/07/21 Removed i24-07-22_760 SKYNET_VPN_ADM_003
6 SKYNET_VPN_ADM_CHANGE_004 2024/07/21 Added i24-07-22_760 SKYNET_VPN_ADM_004
7 SKYNET_VPN_ADM_CHANGE_005 2024/07/21 Added i24-07-22_760 SKYNET_VPN_ADM_005

18
ITD_Firewall.csv Normal file
View file

@ -0,0 +1,18 @@
Index,Name,IP_Address,DNS_Name,Ports_Current,Ports_Requested,Related_Tickets,Description
SKYNET00001,agentjones,193.1.99.72,agentjones,"","","",Firewall (currently not active)
SKYNET00002,vendetta,193.1.99.120,vendetta/ns1,53,"","",DNS Nameserver 1
SKYNET00003,jarvis,193.1.99.73,jarvis,"","","",VM Host
SKYNET00004,vigil,193.1.99.109,vigil/ns2,53,"","",DNS Nameserver 2
SKYNET00005,galatea,193.1.99.111,galatea/stream,80/443 8000,"","",ULFM Radio
SKYNET00006,optimus,193.1.99.112,optimus/games/*.games,80/443 25565,"","",Games server
SKYNET00007,kitt,193.1.99.74,kitt/account/api.account,443,"",i23-07-28_010,"LDAP and Self-Service Password/Account management, also hosts our Discord bot"
SKYNET00008,glados,193.1.99.75,glados/gitlab/*.pages.gitlab,80/443,2222,i23-05-18_249,Gitlab server
SKYNET00009,gir,193.1.99.76,gir/mail/imap/pop3/smtp,80/443 25/143/993/587/465,"",i23-06-19_525/i23-06-19_525,Email and Webmail
SKYNET00010,wheatly,193.1.99.78,wheatly,"","","",Gitlab Runner
SKYNET00011,earth,193.1.99.79,earth,80/443,"",i23-06-19_525,Offical website host
SKYNET00012,skynet,193.1.96.165,skynet/*.users,22 80/443,"",i23-06-30_024,Skynet server. (DMZ)
SKYNET00013,neuromancer,193.1.99.80,neuromancer,"","","",Local Backup Server
SKYNET00014,cadie,193.1.99.77,cadie/nextcloud/onlyoffice.nextcloud,80/443,"",i23-10-27_014,"Services VM, has nextcloud to start with"
SKYNET00015,marvin,193.1.99.81,marvin,,,,Trainee testing server
SKYNET00016,optimus,193.1.99.99,,,,,Games server manager (replacing SKYNET00006 soon)
SKYNET00017,bumblebee,193.1.99.100,,,,,Game server - Minecraft
1 Index Name IP_Address DNS_Name Ports_Current Ports_Requested Related_Tickets Description
2 SKYNET00001 agentjones 193.1.99.72 agentjones Firewall (currently not active)
3 SKYNET00002 vendetta 193.1.99.120 vendetta/ns1 53 DNS Nameserver 1
4 SKYNET00003 jarvis 193.1.99.73 jarvis VM Host
5 SKYNET00004 vigil 193.1.99.109 vigil/ns2 53 DNS Nameserver 2
6 SKYNET00005 galatea 193.1.99.111 galatea/stream 80/443 8000 ULFM Radio
7 SKYNET00006 optimus 193.1.99.112 optimus/games/*.games 80/443 25565 Games server
8 SKYNET00007 kitt 193.1.99.74 kitt/account/api.account 443 i23-07-28_010 LDAP and Self-Service Password/Account management, also hosts our Discord bot
9 SKYNET00008 glados 193.1.99.75 glados/gitlab/*.pages.gitlab 80/443 2222 i23-05-18_249 Gitlab server
10 SKYNET00009 gir 193.1.99.76 gir/mail/imap/pop3/smtp 80/443 25/143/993/587/465 i23-06-19_525/i23-06-19_525 Email and Webmail
11 SKYNET00010 wheatly 193.1.99.78 wheatly Gitlab Runner
12 SKYNET00011 earth 193.1.99.79 earth 80/443 i23-06-19_525 Offical website host
13 SKYNET00012 skynet 193.1.96.165 skynet/*.users 22 80/443 i23-06-30_024 Skynet server. (DMZ)
14 SKYNET00013 neuromancer 193.1.99.80 neuromancer Local Backup Server
15 SKYNET00014 cadie 193.1.99.77 cadie/nextcloud/onlyoffice.nextcloud 80/443 i23-10-27_014 Services VM, has nextcloud to start with
16 SKYNET00015 marvin 193.1.99.81 marvin Trainee testing server
17 SKYNET00016 optimus 193.1.99.99 Games server manager (replacing SKYNET00006 soon)
18 SKYNET00017 bumblebee 193.1.99.100 Game server - Minecraft

View file

@ -1,9 +0,0 @@
MIT License
Copyright (c) 2024 Skynet
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -1,6 +1,5 @@
https://web.archive.org/web/20180815150202/https://wiki.skynet.ie/Admin/SkynetMachines https://web.archive.org/web/20180815150202/https://wiki.skynet.ie/Admin/SkynetMachines
https://en.m.wikipedia.org/wiki/Category:Fictional_artificial_intelligences https://en.m.wikipedia.org/wiki/Category:Fictional_artificial_intelligences
https://en.wikipedia.org/wiki/List_of_artificial_intelligence_films
* agentsmith * agentsmith
* skynet * skynet

View file

@ -43,7 +43,7 @@ colmena build --on @active-dns
Deploying is putting (apply-ing) the config tat was built onto the server, there is no need to build first, it will automatically do so. Deploying is putting (apply-ing) the config tat was built onto the server, there is no need to build first, it will automatically do so.
While the ***recommended way of deploying is using the CI/CD process*** there are times when you will have to manually deploy the config. While the ***recommended way of deploying is using the CI/CD process*** there are times when you will have to manually deploy the config.
One such case is the ``@active-git`` group if either Gitlab or Gitlab-runner got updated. One such case is the ``@active-gitlab`` group if either Gitlab or Gitlab-runner got updated.
Another is if ye have fecked up DNS. Another is if ye have fecked up DNS.
Your ``~/.ssh/config`` should be set up as follows and you should be a member of ``skynet-admins-linux`` Your ``~/.ssh/config`` should be set up as follows and you should be a member of ``skynet-admins-linux``
@ -60,10 +60,10 @@ Then you can run the following commands like so:
```shell ```shell
colmena apply colmena apply
colmena apply --on @active-dns colmena apply --on @active-dns
colmena apply --on @active-git colmena apply --on @active-gitlab
``` ```
The CI/CD pipeline has a manual job that can be triggered to update ``@active-git`` if you know it wont cause issues. The CI/CD pipeline has a manual job that can be triggered to update ``@active-gitlab`` if you know it wont cause issues.
### Agenix ### Agenix

19
_types/dns_object.nix Normal file
View file

@ -0,0 +1,19 @@
{lib, ...}:
with lib; {
options = {
record = mkOption {
type = types.str;
};
r_type = mkOption {
type = types.enum ["A" "CNAME" "TXT" "PTR" "SRV" "MX"];
};
value = mkOption {
type = types.str;
};
server = mkOption {
description = "Core record for a server";
type = types.bool;
default = false;
};
};
}

View file

@ -1,101 +0,0 @@
{
config,
lib,
pkgs,
...
}:
with lib; let
# root service
cfg = config.services.skynet;
in {
imports = [
# every server needs to have a dns record
./dns/dns.nix
# every server should have proper certs
./acme.nix
./nginx.nix
# every server may need the firewall config stuff
./firewall.nix
# every server needs teh ldap client for admins
./ldap/client.nix
# every server will need the config to backup to
./restic.nix
# every server will be monitored for grafana
./prometheus.nix
];
options.services.skynet = {
# since we use this basically everywhere provide a standard way to set it
host = {
ip = mkOption {
type = types.str;
};
name = mkOption {
type = types.str;
};
hostname = mkOption {
type = types.str;
default = "${cfg.host.name}.skynet.ie";
};
interface = mkOption {
type = types.str;
description = "Will most likely be ``eno1`` for physical servers.";
default = "eth0";
};
cidr = mkOption {
type = types.int;
description = "Most of our servers are /26, ";
default = 26;
};
};
};
config = {
services.skynet.dns.records = [
{
record = cfg.host.name;
r_type = "A";
value = cfg.host.ip;
server = true;
}
{
record = cfg.host.ip;
r_type = "PTR";
value = cfg.host.hostname;
}
];
# use lix instead of nix
nix.package = pkgs.lixPackageSets.stable.lix;
# set
networking = {
hostName = cfg.host.name;
defaultGateway.interface = lib.mkForce cfg.host.interface;
# needs to have an address statically assigned
interfaces."${cfg.host.interface}".ipv4.addresses = [
{
address = cfg.host.ip;
prefixLength = cfg.host.cidr;
}
];
};
services.nginx = {
virtualHosts = {
# for every server unless explisitly defined redirect the ip to skynet.ie
"${cfg.host.ip}" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/".return = "307 https://skynet.ie";
};
};
};
};
}

View file

@ -1,165 +0,0 @@
{
config,
pkgs,
lib,
inputs,
...
}:
with lib; let
name = "games_minecraft";
cfg = config.services.skynet."${name}";
# got tired of how long this is so I created a var for it.
short_domain = "${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}";
in {
imports = [
inputs.arion.nixosModules.arion
];
options.services.skynet."${name}" = {
enable = mkEnableOption "Skynet Games Minecraft";
domain = {
tld = mkOption {
type = types.str;
default = "ie";
};
base = mkOption {
type = types.str;
default = "skynet";
};
sub = mkOption {
type = types.str;
default = "minecraft.games";
};
};
};
config = mkIf cfg.enable {
skynet_firewall.forward = [
"ip daddr ${config.services.skynet.host.ip} tcp dport 80 counter packets 0 bytes 0 accept"
"ip daddr ${config.services.skynet.host.ip} tcp dport 443 counter packets 0 bytes 0 accept"
"ip daddr ${config.services.skynet.host.ip} tcp dport 25565 counter packets 0 bytes 0 accept"
];
services.skynet.acme.domains = [
"${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}"
"*.${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}"
];
services.skynet.dns.records = [
# the minecraft (web) config server
{
record = "config.${cfg.domain.sub}";
r_type = "CNAME";
value = config.services.skynet.host.name;
}
# our own minecraft hosts
{
record = "compsoc_classic.${cfg.domain.sub}";
r_type = "CNAME";
value = config.services.skynet.host.name;
}
{
record = "compsoc.${cfg.domain.sub}";
r_type = "CNAME";
value = config.services.skynet.host.name;
}
# gsoc servers
{
record = "gsoc.${cfg.domain.sub}";
r_type = "CNAME";
value = config.services.skynet.host.name;
}
{
record = "gsoc_abridged.${cfg.domain.sub}";
r_type = "CNAME";
value = config.services.skynet.host.name;
}
# phildeb
{
record = "phildeb.${cfg.domain.sub}";
r_type = "CNAME";
value = config.services.skynet.host.name;
}
];
networking.firewall.allowedTCPPorts = [
# for the proxy
25565
];
services.nginx.virtualHosts = {
# https://config.minecraft.games.skynet.ie
"config.${short_domain}" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/" = {
proxyPass = "https://localhost:8443";
proxyWebsockets = true;
};
};
# https://compsoc_classic.minecraft.games.skynet.ie/map/
"compsoc_classic.${short_domain}" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/map/".alias = "/etc/games/minecraft/craftycontrol/servers/f4c5eb33-c6d6-421c-81ab-ded31f6e8750/plugins/dynmap/web/";
};
};
# arion is one way to use docker on nixos
# see https://gitlab.com/c2842/computer_society/nixos/-/blob/733b867f4782afa795848135a83e97a5cafaf16a/applications/games/minecraft.nix
# for an example of a single compose file with multiple services
virtualisation.arion = {
backend = "docker";
projects = {
minecraft.settings.services = {
mc_proxy.service = {
image = "itzg/mc-router:1.18.0";
ports = ["25565:25565/tcp"];
expose = ["25565"];
command = [
"--mapping=compsoc_classic.${short_domain}=mc_config:20000,compsoc.${short_domain}=mc_config:20001,gsoc.${short_domain}=mc_config:20002,gsoc.${short_domain}=mc_config:20002,gsoc_abridged.${short_domain}=mc_config:20003,phildeb.${short_domain}=mc_config:20004"
];
};
mc_config.service = {
image = "registry.gitlab.com/crafty-controller/crafty-4:4.1.1";
environment = {
TZ = "Etc/UTC";
};
volumes = [
"/etc/games/minecraft/craftycontrol/backups:/crafty/backups"
"/etc/games/minecraft/craftycontrol/logs:/crafty/logs"
"/etc/games/minecraft/craftycontrol/servers:/crafty/servers"
"/etc/games/minecraft/craftycontrol/config:/crafty/app/config"
"/etc/games/minecraft/craftycontrol/import:/crafty/import"
];
ports = [
# this ius https only
"8443:8443/tcp"
# compsoc classic
"20000:20000/tcp"
# compsoc
"20001:20001/tcp"
# games
"20002:20002/tcp"
"20003:20003/tcp"
# phildeb
"20004:20004/tcp"
];
};
};
};
};
};
}

View file

@ -5,21 +5,21 @@
... ...
}: }:
with lib; let with lib; let
name = "acme"; cfg = config.skynet_acme;
cfg = config.services.skynet."${name}";
in { in {
imports = []; imports = [];
options.services.skynet."${name}" = { options = {
domains = lib.mkOption { skynet_acme = {
default = []; domains = lib.mkOption {
type = lib.types.listOf lib.types.str; default = [];
description = '' type = lib.types.listOf lib.types.str;
A list of domains to use for this server. description = ''
''; A list of domains to use for this server.
'';
};
}; };
}; };
config = { config = {
# group that will own the certificates # group that will own the certificates
users.groups.acme = {}; users.groups.acme = {};
@ -27,19 +27,20 @@ in {
age.secrets.acme.file = ../secrets/dns_certs.secret.age; age.secrets.acme.file = ../secrets/dns_certs.secret.age;
security.acme = { security.acme = {
preliminarySelfsigned = false;
acceptTerms = true; acceptTerms = true;
defaults = { defaults = {
email = "admin_acme@skynet.ie"; email = "admin_acme@skynet.ie";
credentialsFile = config.age.secrets.acme.path;
# we use our own dns authorative server for verifying we own the domain. # we use our own dns authorative server for verifying we own the domain.
dnsProvider = "rfc2136"; dnsProvider = "rfc2136";
credentialsFile = config.age.secrets.acme.path;
}; };
certs = { certs = {
"skynet" = { "skynet" = {
domain = "skynet.ie"; domain = "skynet.ie";
extraDomainNames = lists.naturalSort cfg.domains; extraDomainNames = cfg.domains;
}; };
}; };
}; };

View file

@ -0,0 +1,324 @@
{
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.services.bitwarden-directory-connector-cli;
in {
disabledModules = ["services/security/bitwarden-directory-connector-cli.nix"];
options.services.bitwarden-directory-connector-cli = {
enable = mkEnableOption "Bitwarden Directory Connector";
package = mkPackageOption pkgs "bitwarden-directory-connector-cli" {};
domain = mkOption {
type = types.str;
description = lib.mdDoc "The domain the Bitwarden/Vaultwarden is accessible on.";
example = "https://vaultwarden.example.com";
};
user = mkOption {
type = types.str;
description = lib.mdDoc "User to run the program.";
default = "bwdc";
};
interval = mkOption {
type = types.str;
default = "*:0,15,30,45";
description = lib.mdDoc "The interval when to run the connector. This uses systemd's OnCalendar syntax.";
};
ldap = mkOption {
description = lib.mdDoc ''
Options to configure the LDAP connection.
If you used the desktop application to test the configuration you can find the settings by searching for `ldap` in `~/.config/Bitwarden\ Directory\ Connector/data.json`.
'';
default = {};
type = types.submodule ({
config,
options,
...
}: {
freeformType = types.attrsOf (pkgs.formats.json {}).type;
config.finalJSON = builtins.toJSON (removeAttrs config (filter (x: x == "finalJSON" || ! options.${x}.isDefined or false) (attrNames options)));
options = {
finalJSON = mkOption {
type = (pkgs.formats.json {}).type;
internal = true;
readOnly = true;
visible = false;
};
ssl = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc "Whether to use TLS.";
};
startTls = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc "Whether to use STARTTLS.";
};
hostname = mkOption {
type = types.str;
description = lib.mdDoc "The host the LDAP is accessible on.";
example = "ldap.example.com";
};
port = mkOption {
type = types.port;
default = 389;
description = lib.mdDoc "Port LDAP is accessible on.";
};
ad = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc "Whether the LDAP Server is an Active Directory.";
};
pagedSearch = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc "Whether the LDAP server paginates search results.";
};
rootPath = mkOption {
type = types.str;
description = lib.mdDoc "Root path for LDAP.";
example = "dc=example,dc=com";
};
username = mkOption {
type = types.str;
description = lib.mdDoc "The user to authenticate as.";
example = "cn=admin,dc=example,dc=com";
};
};
});
};
sync = mkOption {
description = lib.mdDoc ''
Options to configure what gets synced.
If you used the desktop application to test the configuration you can find the settings by searching for `sync` in `~/.config/Bitwarden\ Directory\ Connector/data.json`.
'';
default = {};
type = types.submodule ({
config,
options,
...
}: {
freeformType = types.attrsOf (pkgs.formats.json {}).type;
config.finalJSON = builtins.toJSON (removeAttrs config (filter (x: x == "finalJSON" || ! options.${x}.isDefined or false) (attrNames options)));
options = {
finalJSON = mkOption {
type = (pkgs.formats.json {}).type;
internal = true;
readOnly = true;
visible = false;
};
removeDisabled = mkOption {
type = types.bool;
default = true;
description = lib.mdDoc "Remove users from bitwarden groups if no longer in the ldap group.";
};
overwriteExisting = mkOption {
type = types.bool;
default = false;
description =
lib.mdDoc "Remove and re-add users/groups, See https://bitwarden.com/help/user-group-filters/#overwriting-syncs for more details.";
};
largeImport = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc "Enable if you are syncing more than 2000 users/groups.";
};
memberAttribute = mkOption {
type = types.str;
description = lib.mdDoc "Attribute that lists members in a LDAP group.";
example = "uniqueMember";
};
creationDateAttribute = mkOption {
type = types.str;
description = lib.mdDoc "Attribute that lists a user's creation date.";
example = "whenCreated";
};
useEmailPrefixSuffix = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc "If a user has no email address, combine a username prefix with a suffix value to form an email.";
};
emailPrefixAttribute = mkOption {
type = types.str;
description = lib.mdDoc "The attribute that contains the users username.";
example = "accountName";
};
emailSuffix = mkOption {
type = types.str;
description = lib.mdDoc "Suffix for the email, normally @example.com.";
example = "@example.com";
};
users = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc "Sync users.";
};
userPath = mkOption {
type = types.str;
description = lib.mdDoc "User directory, relative to root.";
default = "ou=users";
};
userObjectClass = mkOption {
type = types.str;
description = lib.mdDoc "Class that users must have.";
default = "inetOrgPerson";
};
userEmailAttribute = mkOption {
type = types.str;
description = lib.mdDoc "Attribute for a users email.";
default = "mail";
};
userFilter = mkOption {
type = types.str;
description = lib.mdDoc "LDAP filter for users.";
example = "(memberOf=cn=sales,ou=groups,dc=example,dc=com)";
default = "";
};
groups = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc "Whether to sync ldap groups into BitWarden.";
};
groupPath = mkOption {
type = types.str;
description = lib.mdDoc "Group directory, relative to root.";
default = "ou=groups";
};
groupObjectClass = mkOption {
type = types.str;
description = lib.mdDoc "A class that groups will have.";
default = "groupOfNames";
};
groupNameAttribute = mkOption {
type = types.str;
description = lib.mdDoc "Attribute for a name of group.";
default = "cn";
};
groupFilter = mkOption {
type = types.str;
description = lib.mdDoc "LDAP filter for groups.";
example = "(cn=sales)";
default = "";
};
};
});
};
secrets = {
ldap = mkOption {
type = types.str;
description = "Path to file that contains LDAP password for user in {option}`ldap.username";
};
bitwarden = {
client_path_id = mkOption {
type = types.str;
description = "Path to file that contains Client ID.";
};
client_path_secret = mkOption {
type = types.str;
description = "Path to file that contains Client Secret.";
};
};
};
};
config = mkIf cfg.enable {
users.groups."${cfg.user}" = {};
users.users."${cfg.user}" = {
isSystemUser = true;
group = cfg.user;
};
systemd = {
timers.bitwarden-directory-connector-cli = {
description = "Sync timer for Bitwarden Directory Connector";
wantedBy = ["timers.target"];
after = ["network-online.target"];
timerConfig = {
OnCalendar = cfg.interval;
Unit = "bitwarden-directory-connector-cli.service";
Persistent = true;
};
};
services.bitwarden-directory-connector-cli = {
description = "Main process for Bitwarden Directory Connector";
environment = {
BITWARDENCLI_CONNECTOR_APPDATA_DIR = "/tmp";
BITWARDENCLI_CONNECTOR_PLAINTEXT_SECRETS = "true";
};
serviceConfig = {
Type = "oneshot";
User = "${cfg.user}";
PrivateTmp = true;
ExecStartPre = pkgs.writeShellScript "bitwarden_directory_connector-config" ''
set -eo pipefail
# create the config file
${lib.getExe cfg.package} data-file
touch /tmp/data.json.tmp
chmod 600 /tmp/data.json{,.tmp}
${lib.getExe cfg.package} config server ${cfg.domain}
# now login to set credentials
export BW_CLIENTID="$(< ${escapeShellArg cfg.secrets.bitwarden.client_path_id})"
export BW_CLIENTSECRET="$(< ${escapeShellArg cfg.secrets.bitwarden.client_path_secret})"
${lib.getExe cfg.package} login
${lib.getExe pkgs.jq} '.authenticatedAccounts[0] as $account
| .[$account].directoryConfigurations.ldap |= $ldap_data
| .[$account].directorySettings.organizationId |= $orgID
| .[$account].directorySettings.sync |= $sync_data' \
--argjson ldap_data ${escapeShellArg cfg.ldap.finalJSON} \
--arg orgID "''${BW_CLIENTID//organization.}" \
--argjson sync_data ${escapeShellArg cfg.sync.finalJSON} \
/tmp/data.json \
> /tmp/data.json.tmp
mv -f /tmp/data.json.tmp /tmp/data.json
# final config
${lib.getExe cfg.package} config directory 0
${lib.getExe cfg.package} config ldap.password --secretfile ${cfg.secrets.ldap}
'';
ExecStart = "${lib.getExe cfg.package} sync";
};
};
};
};
meta.maintainers = with maintainers; [Silver-Golden];
}

View file

@ -6,7 +6,9 @@
}: let }: let
user = "bwdc"; user = "bwdc";
in { in {
imports = []; imports = [
./bitwarden-directory-connector-cli.nix
];
options = {}; options = {};

View file

@ -6,36 +6,53 @@
... ...
}: }:
with lib; let with lib; let
name = "vaultwarden"; cfg = config.services.skynet_vaultwarden;
cfg = config.services.skynet."${name}";
domain_sub = "pw"; domain_sub = "pw";
domain = "${domain_sub}.skynet.ie"; domain = "${domain_sub}.skynet.ie";
in { in {
imports = [ imports = [
../acme.nix
../dns.nix
../nginx.nix
]; ];
options.services.skynet."${name}" = { options.services.skynet_vaultwarden = {
enable = mkEnableOption "Skynet VaultWarden server"; enable = mkEnableOption "Skynet vaultwarden server";
host = {
ip = mkOption {
type = types.str;
};
name = mkOption {
type = types.str;
};
};
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
#backups = [ "/etc/silver_ul_ical/database.db" ]; #backups = [ "/etc/silver_ul_ical/database.db" ];
# Website config # Website config
services.skynet.acme.domains = [ skynet_acme.domains = [
domain domain
]; ];
services.skynet.dns.records = [ skynet_dns.records = [
{ {
record = domain_sub; record = domain_sub;
r_type = "CNAME"; r_type = "CNAME";
value = config.services.skynet.host.name; value = cfg.host.name;
} }
]; ];
services.nginx.virtualHosts = { services.nginx.virtualHosts = {
"${cfg.host.ip}" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/".return = "307 https://skynet.ie";
};
"${domain}" = { "${domain}" = {
forceSSL = true; forceSSL = true;
useACMEHost = "skynet"; useACMEHost = "skynet";

View file

@ -6,14 +6,13 @@
... ...
}: }:
with lib; let with lib; let
name = "discord_bot"; cfg = config.services.discord_bot;
cfg = config.services.skynet."${name}";
in { in {
imports = [ imports = [
inputs.skynet_discord_bot.nixosModule."x86_64-linux" inputs.skynet_discord_bot.nixosModule."x86_64-linux"
]; ];
options.services.skynet."${name}" = { options.services.discord_bot = {
enable = mkEnableOption "Skynet LDAP backend server"; enable = mkEnableOption "Skynet LDAP backend server";
}; };
@ -21,18 +20,21 @@ in {
#backups = [ "/etc/silver_ul_ical/database.db" ]; #backups = [ "/etc/silver_ul_ical/database.db" ];
age.secrets.discord_token.file = ../secrets/discord/token.age; age.secrets.discord_token.file = ../secrets/discord/token.age;
age.secrets.discord_ldap.file = ../secrets/discord/ldap.age;
age.secrets.discord_mail.file = ../secrets/email/details.age; age.secrets.discord_mail.file = ../secrets/email/details.age;
age.secrets.discord_wolves.file = ../secrets/wolves/details.age; age.secrets.discord_wolves.file = ../secrets/wolves/details.age;
# this is what was imported
services.skynet_discord_bot = { services.skynet_discord_bot = {
enable = true; enable = true;
env = { env = {
discord = config.age.secrets.discord_token.path; discord = config.age.secrets.discord_token.path;
ldap = config.age.secrets.discord_ldap.path;
mail = config.age.secrets.discord_mail.path; mail = config.age.secrets.discord_mail.path;
wolves = config.age.secrets.discord_wolves.path; wolves = config.age.secrets.discord_wolves.path;
}; };
discord.server = "689189992417067052";
}; };
}; };
} }

View file

@ -1,32 +0,0 @@
{
config,
pkgs,
lib,
inputs,
...
}:
with lib; let
name = "discord_bot_t-800";
cfg = config.services.skynet."${name}";
in {
imports = [
inputs.skynet_discord_bot_t-800.nixosModule."x86_64-linux"
];
options.services.skynet."${name}" = {
enable = mkEnableOption "Logging Bot";
};
config = mkIf cfg.enable {
#backups = [ "/etc/silver_ul_ical/database.db" ];
age.secrets.discord_t-800_details.file = ../secrets/discord/t-800.age;
# this is what was imported
services.skynet_discord_bot_t-800 = {
enable = true;
env = config.age.secrets.discord_t-800_details.path;
};
};
}

View file

@ -3,42 +3,18 @@
pkgs, pkgs,
config, config,
nodes, nodes,
self,
... ...
}: let }: let
name = "dns"; cfg = config.skynet_dns;
cfg = config.services.skynet."${name}";
# reads that date to a string (will need to be fixed in 2038) # reads that date to a string (will need to be fixed in 2038)
current_date = self.lastModified; current_date = lib.readFile "${pkgs.runCommand "timestamp" {} "echo -n `date +%s` > $out"}";
# this gets a list of all domains we have records for
domains = lib.lists.naturalSort (lib.lists.unique (
lib.lists.forEach records (x: x.domain)
));
# get the ip's of our servers
servers = lib.lists.naturalSort (lib.lists.unique (
lib.lists.forEach (sort_records_a_server records) (x: x.value)
));
domains_owned = [
# for historic reasons we own this
"csn.ul.ie"
# the main one we use now
"skynet.ie"
# a backup
"ulcompsoc.ie"
];
# gets a list of records that match this type # gets a list of records that match this type
filter_records_type = records: r_type: builtins.filter (x: x.r_type == r_type) records; filter_records_type = records: r_type: builtins.filter (x: x.r_type == r_type) records;
# Get all the A records that are for servers (base record for them) filter_records_server = records: builtins.filter (x: builtins.hasAttr "server" x && x.server) (filter_records_type records "A");
filter_records_a_server = records: builtins.filter (x: builtins.hasAttr "server" x && x.server) (filter_records_type records "A");
# Every other A record
filter_records_a = records: builtins.filter (x: builtins.hasAttr "server" x && !x.server) (filter_records_type records "A"); filter_records_a = records: builtins.filter (x: builtins.hasAttr "server" x && !x.server) (filter_records_type records "A");
# These functions are to get the final 3 digits of an IP address so we can use them for reverse pointer
process_ptr = records: lib.lists.forEach records (x: process_ptr_sub x); process_ptr = records: lib.lists.forEach records (x: process_ptr_sub x);
process_ptr_sub = record: { process_ptr_sub = record: {
record = builtins.substring 9 3 record.record; record = builtins.substring 9 3 record.record;
@ -47,56 +23,35 @@
}; };
ip_ptr_to_int = ip: lib.strings.toInt (builtins.substring 9 3 ip); ip_ptr_to_int = ip: lib.strings.toInt (builtins.substring 9 3 ip);
# filter and sort records so we cna group them in the right place later sort_records_server = records: builtins.sort (a: b: a.record < b.record) (filter_records_server records);
sort_records_a_server = records: builtins.sort (a: b: a.record < b.record) (filter_records_a_server records);
sort_records_a = records: builtins.sort (a: b: (ip_ptr_to_int a.value) < (ip_ptr_to_int b.value)) (filter_records_a records); sort_records_a = records: builtins.sort (a: b: (ip_ptr_to_int a.value) < (ip_ptr_to_int b.value)) (filter_records_a records);
sort_records_cname = records: builtins.sort (a: b: a.value < b.value) (filter_records_type records "CNAME"); sort_records_cname = records: builtins.sort (a: b: a.value < b.value) (filter_records_type records "CNAME");
sort_records_ptr = records: builtins.sort (a: b: (lib.strings.toInt a.record) < (lib.strings.toInt b.record)) (process_ptr (filter_records_type records "PTR")); sort_records_ptr = records: builtins.sort (a: b: (lib.strings.toInt a.record) < (lib.strings.toInt b.record)) (process_ptr (filter_records_type records "PTR"));
sort_records_srv = records: builtins.sort (a: b: a.record < b.record) (filter_records_type records "SRV"); sort_records_srv = records: builtins.sort (a: b: a.record < b.record) (filter_records_type records "SRV");
# a tad overkill but type guarding is useful format_records = records: offset: lib.strings.concatMapStrings (x: "${padString x.record offset} IN ${padString x.r_type 5} ${x.value}\n") records;
max = x: y:
assert builtins.isInt x;
assert builtins.isInt y;
if x < y
then y
else x;
# get teh max length of a list of strings # small function to trim it down a tad
max_len = records: lib.lists.foldr (a: b: (max a b)) 0 (lib.lists.forEach records (record: lib.strings.stringLength record.record));
# Now that we can get teh max lenth of a list of strings
# we can pad it out to the max len +1
# this is so that teh generated file is easier for a human to read
format_records = records: let
offset = (max_len records) + 1;
in
lib.strings.concatMapStrings (x: "${padString x.record offset} IN ${padString x.r_type 5} ${x.value}\n") records;
# small function to add spaces until it reaches teh required length
padString = text: length: fixedWidthString_post length " " text; padString = text: length: fixedWidthString_post length " " text;
# like lib.strings.fixedWidthString but postfix # like lib.strings.fixedWidthString but postfix
# recursive function to extend a string up to a limit
fixedWidthString_post = width: filler: str: let fixedWidthString_post = width: filler: str: let
strw = lib.stringLength str; strw = lib.stringLength str;
reqWidth = width - (lib.stringLength filler); reqWidth = width - (lib.stringLength filler);
in in
# this is here because we were manually setting teh length, now max_len does that for us
assert lib.assertMsg (strw <= width) "fixedWidthString_post: requested string length (${toString width}) must not be shorter than actual length (${toString strw})"; assert lib.assertMsg (strw <= width) "fixedWidthString_post: requested string length (${toString width}) must not be shorter than actual length (${toString strw})";
if strw == width if strw == width
then str then str
else (fixedWidthString_post reqWidth filler str) + filler; else (fixedWidthString_post reqWidth filler str) + filler;
# base config for domains we own (skynet.ie, csn.ul.ie, ulcompsoc.ie) # base config for domains we own (skynet.ie, csn.ul.ie, ulcompsoc.ie)
# ";" are comments in this file
get_config_file = ( get_config_file = (
domain: records: '' domain: records: ''
$TTL 60 ; 1 minute $TTL 60 ; 1 minute
; hostmaster@skynet.ie is an email address that recieves stuff related to dns ; hostmaster@skynet.ie is an email address that recieves stuff related to dns
@ IN SOA ${nameserver}.skynet.ie. hostmaster.skynet.ie. ( @ IN SOA ${nameserver}.skynet.ie. hostmaster.skynet.ie. (
; Serial (YYYYMMDDCC) this has to be updated for each time the record is updated ; Serial (YYYYMMDDCC) this has to be updated for each time the record is updated
${toString current_date} ${current_date}
600 ; Refresh (10 minutes) 600 ; Refresh (10 minutes)
300 ; Retry (5 minutes) 300 ; Retry (5 minutes)
604800 ; Expire (1 week) 604800 ; Expire (1 week)
@ -107,48 +62,54 @@
@ NS ns1.skynet.ie. @ NS ns1.skynet.ie.
@ NS ns2.skynet.ie. @ NS ns2.skynet.ie.
; can have multiple mailserves
@ MX 10 mail.skynet.ie.
; ------------------------------------------ ; ------------------------------------------
; Server Names (A Records) ; Server Names (A Records)
; ------------------------------------------ ; ------------------------------------------
${format_records (sort_records_a_server records)} ${format_records (sort_records_server records) 31}
; ------------------------------------------ ; ------------------------------------------
; A (non server names ; A (non server names
; ------------------------------------------ ; ------------------------------------------
${format_records (sort_records_a records)} ${format_records (sort_records_a records) 31}
; ------------------------------------------ ; ------------------------------------------
; CNAMES ; CNAMES
; ------------------------------------------ ; ------------------------------------------
${format_records (sort_records_cname records)} ${format_records (sort_records_cname records) 31}
; ------------------------------------------ ; ------------------------------------------
; TXT ; TXT
; ------------------------------------------ ; ------------------------------------------
${format_records (filter_records_type records "TXT")} ${format_records (filter_records_type records "TXT") 31}
; ------------------------------------------ ; ------------------------------------------
; MX ; MX
; ------------------------------------------ ; ------------------------------------------
${format_records (filter_records_type records "MX")} ${format_records (filter_records_type records "MX") 31}
; ------------------------------------------ ; ------------------------------------------
; SRV ; SRV
; ------------------------------------------ ; ------------------------------------------
${format_records (sort_records_srv records)} ${format_records (sort_records_srv records) 65}
'' ''
); );
# https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/4/html/reference_guide/s2-bind-configuration-zone-reverse # https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/4/html/reference_guide/s2-bind-configuration-zone-reverse
# config for our reverse dns pointers (not properly working) # config for our reverse dnspointers (not properly working)
get_config_file_rev = ( get_config_file_rev = (
domain: '' domain: records: ''
$ORIGIN 64-64.99.1.193.in-addr.arpa. $ORIGIN 64-64.99.1.193.in-addr.arpa.
$TTL 60 ; 1 minute $TTL 60 ; 1 minute
; hostmaster@skynet.ie is an email address that recieves stuff related to dns ; hostmaster@skynet.ie is an email address that recieves stuff related to dns
@ IN SOA ${nameserver}.skynet.ie. hostmaster.skynet.ie. ( @ IN SOA ${nameserver}.skynet.ie. hostmaster.skynet.ie. (
; Serial (YYYYMMDDCC) this has to be updated for each time the record is updated ; Serial (YYYYMMDDCC) this has to be updated for each time the record is updated
${toString current_date} ${current_date}
600 ; Refresh (10 minutes) 600 ; Refresh (10 minutes)
300 ; Retry (5 minutes) 300 ; Retry (5 minutes)
604800 ; Expire (1 week) 604800 ; Expire (1 week)
@ -161,37 +122,35 @@
; ------------------------------------------ ; ------------------------------------------
; PTR ; PTR
; ------------------------------------------ ; ------------------------------------------
${format_records (sort_records_ptr records)} ${format_records (sort_records_ptr records) 3}
'' ''
); );
# arrays of teh two nameservers # arrys of teh two nameservers
nameserver_1 = ["193.1.99.109"]; tmp1 = ["193.1.99.109"];
nameserver_2 = ["193.1.99.120"]; tmp2 = ["193.1.99.120"];
primaries = ( primaries = (
if cfg.server.primary if cfg.server.primary
then then
# primary servers have no primaries (ones they listen to) # primary servers have no primaries (ones they listen to)
[] []
else if builtins.elem cfg.server.ip nameserver_1 else if builtins.elem cfg.server.ip tmp1
then nameserver_2 then tmp2
else nameserver_1 else tmp1
); );
secondaries = ( secondaries = (
if cfg.server.primary if cfg.server.primary
then then
if builtins.elem cfg.server.ip nameserver_1 if builtins.elem cfg.server.ip tmp1
then nameserver_2 then tmp2
else nameserver_1 else tmp1
else [] else []
); );
# small function to tidy up the spam of the cache networks, would use teh subnet except all external traffic has the ip of teh router # small function to tidy up the spam of the cache networks, would use teh subnet except all external traffic has the ip of teh router
# now limited explicitly to servers that we are administering create_cache_networks = map (x: "193.1.99.${toString x}/32") (lib.lists.range 71 126);
# See i24-09-30_050 for more information
create_cache_networks = map (x: "${toString x}/32") servers;
# standard function to create the etc file, pass in the text and domain and it makes it # standard function to create the etc file, pass in the text and domain and it makes it
create_entry_etc_sub = domain: text: { create_entry_etc_sub = domain: text: {
@ -203,38 +162,37 @@
# The UNIX file mode bits # The UNIX file mode bits
mode = "0664"; mode = "0664";
# content of the file
text = text; text = text;
}; };
}; };
# (text.owned "csn.ul.ie")
# standard function to create the etc file, pass in the text and domain and it makes it # standard function to create the etc file, pass in the text and domain and it makes it
create_entry_etc = domain: type: let create_entry_etc = domain: type: records:
domain_records = lib.lists.filter (x: x.domain == domain) records;
in
# this is the main type of record that most folks are used to
if type == "owned" if type == "owned"
then create_entry_etc_sub domain (get_config_file domain domain_records) then create_entry_etc_sub domain (text.owned domain records)
# reverse lookups allow for using an IP to find domains pointing to it
else if type == "reverse" else if type == "reverse"
then create_entry_etc_sub domain (get_config_file_rev domain) then create_entry_etc_sub domain (text.reverse domain records)
else {}; else {};
create_entry_zone = domain: let create_entry_zone_names = builtins.attrNames (removeAttrs config.skynet.records ["skynet.ie"]);
if_primary_and_owned = create_entry_zone_mapped = map (x: (create_entry_zone x)) create_entry_zone_names;
if cfg.server.primary && (lib.lists.any (item: item == domain) domains_owned) create_entry_zone_attr = lib.mkMerge create_entry_zone_mapped;
then ''
allow-update { key rfc2136key.skynet.ie.; }; create_entry_etc_mapped = map (x: (create_entry_etc x "owned" config.skynet.records.${x})) create_entry_zone_names;
dnssec-policy default; create_entry_etc_attr = lib.mkMerge create_entry_etc_mapped;
inline-signing yes;
'' create_entry_zone = domain: {
else "";
in {
"${domain}" = { "${domain}" = {
extraConfig = '' extraConfig = ''
${if_primary_and_owned} allow-update {
key rfc2136key.${domain}.;
};
dnssec-policy default;
inline-signing yes;
// for bumping the config // for bumping the config
// ${toString current_date} // ${current_date}
''; '';
# really wish teh nixos config didnt use master/slave # really wish teh nixos config didnt use master/slave
master = cfg.server.primary; master = cfg.server.primary;
@ -247,16 +205,51 @@
}; };
}; };
text = {
owned = domain: records: get_config_file domain records;
reverse = domain: records: get_config_file_rev domain records;
};
records = records =
config.skynet.records config.skynet.records."skynet.ie"
/*
Need to "manually" grab it from each server.
Nix is laxy evalusted so if it does not need to open a file it wont.
This is to iterate through each server (node) and evaluate the dns records for that server.
*/
++ builtins.concatLists ( ++ builtins.concatLists (
lib.attrsets.mapAttrsToList ( lib.attrsets.mapAttrsToList (
key: value: value.config.services.skynet.dns.records key: value: let
details_server = value.config.skynet_dns.server;
details_records = value.config.skynet_dns.records;
in
if builtins.hasAttr "skynet_dns" value.config
then
(
# got to handle habing a dns record for the dns serves themselves.
if details_server.enable
then
(
if details_server.primary
then
details_records
++ [
{
record = "ns1";
r_type = "A";
value = details_server.ip;
server = false;
}
]
else
details_records
++ [
{
record = "ns2";
r_type = "A";
value = details_server.ip;
server = false;
}
]
)
else details_records
)
else []
) )
nodes nodes
); );
@ -267,46 +260,43 @@
else "ns2"; else "ns2";
in { in {
imports = [ imports = [
../../config/dns.nix ./firewall.nix
../config/dns.nix
]; ];
options.services.skynet."${name}" = { options = {
server = { skynet_dns = {
enable = lib.mkEnableOption { server = {
default = false; enable = lib.mkEnableOption {
description = "Skynet DNS server"; default = false;
type = lib.types.bool; description = "Skynet DNS server";
type = lib.types.bool;
};
primary = lib.mkOption {
type = lib.types.bool;
default = false;
};
ip = lib.mkOption {
type = lib.types.str;
description = ''
ip of this server
'';
};
}; };
primary = lib.mkOption { records = lib.mkOption {
type = lib.types.bool; description = "Records, sorted based on therir type";
default = false; type = lib.types.listOf (lib.types.submodule (import ../_types/dns_object.nix {
inherit lib;
}));
}; };
ip = lib.mkOption {
type = lib.types.str;
description = ''
ip of this server
'';
};
};
records = lib.mkOption {
description = "Records, sorted based on therir type";
type = lib.types.listOf (lib.types.submodule (import ./options-records.nix {
inherit lib;
}));
}; };
}; };
config = lib.mkIf cfg.server.enable { config = lib.mkIf cfg.server.enable {
# logging # services.skynet_backup.normal.backups = ["/etc/skynet/dns"];
services.prometheus.exporters.bind = {
enable = true;
openFirewall = true;
};
# services.skynet.backup.normal.backups = ["/etc/skynet/dns"];
# open the firewall for this # open the firewall for this
skynet_firewall.forward = [ skynet_firewall.forward = [
@ -314,40 +304,29 @@ in {
"ip daddr ${cfg.server.ip} udp dport 53 counter packets 0 bytes 0 accept" "ip daddr ${cfg.server.ip} udp dport 53 counter packets 0 bytes 0 accept"
]; ];
services.skynet.dns.records = [ services.bind.zones = lib.mkMerge [
{ (create_entry_zone "csn.ul.ie")
record = nameserver; (create_entry_zone "skynet.ie")
r_type = "A"; (create_entry_zone "ulcompsoc.ie")
value = config.services.skynet.host.ip; (create_entry_zone "64-64.99.1.193.in-addr.arpa")
} create_entry_zone_attr
]; ];
services.bind.zones = lib.attrsets.mergeAttrsList ( environment.etc = lib.mkMerge [
# uses teh domains lsited in teh records (create_entry_etc "csn.ul.ie" "owned" records)
(lib.lists.forEach domains (domain: (create_entry_zone domain))) (create_entry_etc "skynet.ie" "owned" records)
# we have to do a reverse dns (create_entry_etc "ulcompsoc.ie" "owned" records)
++ [ (create_entry_etc "64-64.99.1.193.in-addr.arpa" "reverse" records)
(create_entry_zone "64-64.99.1.193.in-addr.arpa") create_entry_etc_attr
] ];
);
environment.etc = lib.attrsets.mergeAttrsList (
# uses teh domains lsited in teh records
(lib.lists.forEach domains (domain: (create_entry_etc domain "owned")))
# we have to do a reverse dns
++ [
(create_entry_etc "64-64.99.1.193.in-addr.arpa" "reverse")
]
);
# secrets required # secrets required
age.secrets.dns_dnskeys = { age.secrets.dns_dnskeys = {
file = ../../secrets/dns_dnskeys.conf.age; file = ../secrets/dns_dnskeys.conf.age;
owner = "named"; owner = "named";
group = "named"; group = "named";
}; };
# basic but ensure teh dns ports are open
networking.firewall = { networking.firewall = {
allowedTCPPorts = [53]; allowedTCPPorts = [53];
allowedUDPPorts = [53]; allowedUDPPorts = [53];
@ -361,15 +340,11 @@ in {
# need to take a look at https://nixos.org/manual/nixos/unstable/#module-security-acme-config-dns # need to take a look at https://nixos.org/manual/nixos/unstable/#module-security-acme-config-dns
extraConfig = '' extraConfig = ''
include "/run/agenix/dns_dnskeys"; include "/run/agenix/dns_dnskeys";
statistics-channels {
inet 127.0.0.1 port 8053 allow { 127.0.0.1; };
};
''; '';
# piles of no valid RRSIG resolving 'com/DS/IN' errors # piles of no valid RRSIG resolving 'com/DS/IN' errors
extraOptions = '' extraOptions = ''
dnssec-validation auto; dnssec-validation yes;
''; '';
# set the upstream dns servers # set the upstream dns servers

View file

@ -1,31 +0,0 @@
/*
Define the options for dns records here.
They are imported into anything that needs to use them
*/
{lib, ...}:
with lib; {
options = {
domain = lib.mkOption {
description = "Domain this record is for";
type = lib.types.str;
default = "skynet.ie";
};
record = lib.mkOption {
description = "What you want to name the subdomain.";
type = lib.types.str;
};
r_type = lib.mkOption {
description = "Type of record that this is.";
type = lib.types.enum ["A" "CNAME" "TXT" "PTR" "SRV" "MX"];
};
value = lib.mkOption {
description = "What the record points to, normally ip or another record.";
type = lib.types.str;
};
server = lib.mkOption {
description = "Core record for a server";
type = lib.types.bool;
default = false;
};
};
}

View file

@ -6,8 +6,7 @@
... ...
}: }:
with lib; let with lib; let
name = "email"; cfg = config.services.skynet_email;
cfg = config.services.skynet."${name}";
# create teh new strings # create teh new strings
create_filter_array = map (x: "(memberOf=cn=${x},ou=groups,${cfg.ldap.base})"); create_filter_array = map (x: "(memberOf=cn=${x},ou=groups,${cfg.ldap.base})");
@ -50,10 +49,6 @@ with lib; let
account = "contact"; account = "contact";
members = ["committee"]; members = ["committee"];
} }
{
account = "committee";
members = ["committee"];
}
{ {
account = "dbadmin"; account = "dbadmin";
members = ["admin"]; members = ["admin"];
@ -96,7 +91,7 @@ with lib; let
} }
]; ];
sieveConfigFile = configFile =
# https://doc.dovecot.org/configuration_manual/sieve/examples/#plus-addressed-mail-filtering # https://doc.dovecot.org/configuration_manual/sieve/examples/#plus-addressed-mail-filtering
pkgs.writeText "basic_sieve" pkgs.writeText "basic_sieve"
'' ''
@ -106,71 +101,48 @@ with lib; let
require ["fileinto", "reject"]; require ["fileinto", "reject"];
require "variables"; require "variables";
require "regex"; require "regex";
require "subaddress";
# this should be close to teh last step # this should be close to teh last step
if allof ( if allof (
address :user ["To", "Cc"] ["${toString create_config_to}"], address :localpart ["To"] ["${toString create_config_to}"],
address :domain ["To", "Cc"] "skynet.ie" address :domain ["To"] "skynet.ie"
){ ){
if address :matches ["To", "Cc"] "*@skynet.ie" { if address :matches ["To"] "*@skynet.ie" {
# handle spam reports specifically for teh service accounts in each users inbox if header :is "X-Spam" "Yes" {
if address :matches ["From"] "postmaster@mimi.skynet.ie" { fileinto :create "''${1}.Junk";
fileinto :create "''${1}.Spam_Report"; stop;
stop; } else {
fileinto :create "''${1}";
}
} }
# user+subdir
if address :matches ["To", "Cc"] "*+*@skynet.ie" {
fileinto :create "''${1}.''${2}";
stop;
}
# no detail, proceed normally
if header :is "X-Spam" "Yes" {
fileinto :create "''${1}.Junk";
stop;
} else {
fileinto :create "''${1}";
stop;
}
}
}
# handle spam Reports for general users
if address :matches ["From"] "postmaster@mimi.skynet.ie" {
fileinto :create "INBOX.Spam_Report";
stop;
}
if allof (
address :localpart ["From"] ["${toString create_config_to}"],
address :domain ["From"] "skynet.ie"
){
if address :matches ["From"] "*@skynet.ie" {
if header :is "X-Spam" "Yes" {
fileinto :create "''${1}.Junk";
stop;
} else {
fileinto :create "''${1}";
stop;
}
}
} }
''; '';
in { in {
imports = [ imports = [
./dns.nix
./acme.nix
./nginx.nix
inputs.simple-nixos-mailserver.nixosModule inputs.simple-nixos-mailserver.nixosModule
# for teh config # for teh config
../config/users.nix ../config/users.nix
]; ];
options.services.skynet."${name}" = { options.services.skynet_email = {
# options that need to be passed in to make this work # options that need to be passed in to make this work
enable = mkEnableOption "Skynet Email"; enable = mkEnableOption "Skynet Email";
host = {
ip = mkOption {
type = types.str;
};
name = mkOption {
type = types.str;
};
};
domain = mkOption { domain = mkOption {
type = types.str; type = types.str;
default = "skynet.ie"; default = "skynet.ie";
@ -226,8 +198,8 @@ in {
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
services.skynet.backup.normal.backups = [ services.skynet_backup.normal.backups = [
#"/var/vmail" "/var/vmail"
"/var/dkim" "/var/dkim"
]; ];
@ -273,6 +245,12 @@ in {
# to provide the certs # to provide the certs
services.nginx.virtualHosts = { services.nginx.virtualHosts = {
"${cfg.host.ip}" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/".return = "307 https://skynet.ie";
};
"mail.skynet.ie" = { "mail.skynet.ie" = {
forceSSL = true; forceSSL = true;
useACMEHost = "mail"; useACMEHost = "mail";
@ -307,128 +285,95 @@ in {
}; };
# set up dns record for it # set up dns record for it
services.skynet.dns.records = skynet_dns.records = [
[ # basic one
{ {
# This is the mail gateway, try to send all mail to it first record = "mail";
# Lower number = higher priority r_type = "A";
record = "@"; value = cfg.host.ip;
r_type = "MX"; }
# the number is the priority in teh case of multiple mailservers #DNS config for K-9 Mail
value = "5 mimi.${cfg.domain}."; {
} record = "imap";
{ r_type = "CNAME";
# this is the main email server value = "mail";
record = "@"; }
r_type = "MX"; {
# the number is the priority in teh case of multiple mailservers record = "pop3";
value = "10 mail.${cfg.domain}."; r_type = "CNAME";
} value = "mail";
{ }
record = "@"; {
r_type = "MX"; record = "smtp";
# the number is the priority in teh case of multiple mailservers r_type = "CNAME";
value = "10 lists.${cfg.domain}."; value = "mail";
} }
# basic one # TXT records, all tehse are inside escaped strings to allow using ""
{
record = "mail";
r_type = "A";
value = config.services.skynet.host.ip;
}
{
record = "lists";
r_type = "A";
value = config.services.skynet.host.ip;
}
#DNS config for K-9 Mail
{
record = "imap";
r_type = "CNAME";
value = "mail";
}
{
record = "pop3";
r_type = "CNAME";
value = "mail";
}
{
record = "smtp";
r_type = "CNAME";
value = "mail";
}
# TXT records, all tehse are inside escaped strings to allow using ""
# reverse pointer
{
record = config.services.skynet.host.ip;
r_type = "PTR";
value = "${cfg.sub}.${cfg.domain}.";
}
# SRV records to help gmail on android etc find the correct mail.skynet.ie domain for config rather than just defaulting to skynet.ie
# https://serverfault.com/questions/935192/how-to-setup-auto-configure-email-for-android-mail-app-on-your-server/1018406#1018406
# response should be:
# _imap._tcp SRV 0 1 143 imap.example.com.
{
record = "_imaps._tcp";
r_type = "SRV";
value = "0 1 993 ${cfg.sub}.${cfg.domain}.";
}
{
record = "_imap._tcp";
r_type = "SRV";
value = "0 1 143 ${cfg.sub}.${cfg.domain}.";
}
{
record = "_submissions._tcp";
r_type = "SRV";
value = "0 1 465 ${cfg.sub}.${cfg.domain}.";
}
{
record = "_submission._tcp";
r_type = "SRV";
value = "0 1 587 ${cfg.sub}.${cfg.domain}.";
}
]
# SPF record # SPF record
++ [ {
{ record = "${cfg.domain}.";
record = "${cfg.domain}."; r_type = "TXT";
r_type = "TXT"; value = ''"v=spf1 a:${cfg.sub}.${cfg.domain} -all"'';
value = ''"v=spf1 a:${cfg.sub}.${cfg.domain} ip4:${config.services.skynet.host.ip} -all"''; }
}
]
# DKIM keys # DKIM keys
++ [ {
{ record = "mail._domainkey.skynet.ie.";
record = "mail._domainkey.skynet.ie."; r_type = "TXT";
r_type = "TXT"; value = ''"v=DKIM1; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxju1Ie60BdHwyFVPNQKovL/cX9IFPzBKgjnHZf+WBzDCFKSBpf7NvnfXajtFDQN0poaN/Qfifid+V55ZCNDBn8Y3qZa4Y69iNiLw2DdvYf0HdnxX6+pLpbmj7tikGGLJ62xnhkJhoELnz5gCOhpyoiv0tSQVaJpaGZmoll861/QIDAQAB"'';
value = ''"v=DKIM1; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxju1Ie60BdHwyFVPNQKovL/cX9IFPzBKgjnHZf+WBzDCFKSBpf7NvnfXajtFDQN0poaN/Qfifid+V55ZCNDBn8Y3qZa4Y69iNiLw2DdvYf0HdnxX6+pLpbmj7tikGGLJ62xnhkJhoELnz5gCOhpyoiv0tSQVaJpaGZmoll861/QIDAQAB"''; }
} {
{ record = "mail._domainkey.ulcompsoc.ie.";
domain = "ulcompsoc.ie"; r_type = "TXT";
record = "mail._domainkey.ulcompsoc.ie."; value = ''"v=DKIM1; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDl8ptSASx37t5sfmU2d2Y6yi9AVrsNFBZDmJ2uaLa4NuvAjxGQCw4wx+1Jui/HOuKYLpntLsjN851wgPR+3i51g4OblqBDvcHn9NYgWRZfHj9AASANQjdsaAbkXuyKuO46hZqeWlpESAcD6a4Evam4fkm+kiZC0+rccb4cWgsuLwIDAQAB"'';
r_type = "TXT"; }
value = ''"v=DKIM1; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDl8ptSASx37t5sfmU2d2Y6yi9AVrsNFBZDmJ2uaLa4NuvAjxGQCw4wx+1Jui/HOuKYLpntLsjN851wgPR+3i51g4OblqBDvcHn9NYgWRZfHj9AASANQjdsaAbkXuyKuO46hZqeWlpESAcD6a4Evam4fkm+kiZC0+rccb4cWgsuLwIDAQAB"'';
}
]
# DMARC # DMARC
++ [ {
{ record = "_dmarc.${cfg.domain}.";
record = "_dmarc.${cfg.domain}."; r_type = "TXT";
r_type = "TXT"; # p : quarantine => sends to spam, reject => never sent
# p : quarantine => sends to spam, reject => never sent # rua : mail that receives reports about DMARC activity
# rua : mail that receives reports about DMARC activity # pct : percentage of unathenticated messages that DMARC stops
# pct : percentage of unathenticated messages that DMARC stops # adkim : alignment policy for DKIM, s => Strict, subdomains arent allowed, r => relaxed, subdomains allowed
# adkim : alignment policy for DKIM, s => Strict, subdomains arent allowed, r => relaxed, subdomains allowed # aspf : alignment policy for SPF, s => Strict, subdomains arent allowed, r => relaxed, subdomains allowed
# aspf : alignment policy for SPF, s => Strict, subdomains arent allowed, r => relaxed, subdomains allowed # sp : DMARC policy for subdomains, none => no action, reports to rua, quarantine => spam, reject => never sent
# sp : DMARC policy for subdomains, none => no action, reports to rua, quarantine => spam, reject => never sent value = ''"v=DMARC1; p=quarantine; rua=mailto:mailman@skynet.ie; pct=100; adkim=s; aspf=s; sp=none"'';
value = ''"v=DMARC1; p=quarantine; rua=mailto:mailman@skynet.ie; pct=100; adkim=s; aspf=s; sp=quarantine"''; }
}
]; # reverse pointer
{
record = cfg.host.ip;
r_type = "PTR";
value = "${cfg.sub}.${cfg.domain}.";
}
# SRV records to help gmail on android etc find the correct mail.skynet.ie domain for config rather than just defaulting to skynet.ie
# https://serverfault.com/questions/935192/how-to-setup-auto-configure-email-for-android-mail-app-on-your-server/1018406#1018406
# response should be:
# _imap._tcp SRV 0 1 143 imap.example.com.
{
record = "_imaps._tcp";
r_type = "SRV";
value = "0 1 993 ${cfg.sub}.${cfg.domain}.";
}
{
record = "_imap._tcp";
r_type = "SRV";
value = "0 1 143 ${cfg.sub}.${cfg.domain}.";
}
{
record = "_submissions._tcp";
r_type = "SRV";
value = "0 1 465 ${cfg.sub}.${cfg.domain}.";
}
{
record = "_submission._tcp";
r_type = "SRV";
value = "0 1 587 ${cfg.sub}.${cfg.domain}.";
}
];
#https://nixos-mailserver.readthedocs.io/en/latest/add-roundcube.html #https://nixos-mailserver.readthedocs.io/en/latest/add-roundcube.html
users.groups.nginx = {}; users.groups.nginx = {};
@ -470,12 +415,9 @@ in {
mailserver = { mailserver = {
enable = true; enable = true;
stateVersion = 3;
fqdn = "${cfg.sub}.${cfg.domain}"; fqdn = "${cfg.sub}.${cfg.domain}";
domains = [ domains = [
cfg.domain cfg.domain
"lists.skynet.ie"
]; ];
enableManageSieve = true; enableManageSieve = true;
@ -490,10 +432,6 @@ in {
# 20MB max size # 20MB max size
messageSizeLimit = 20000000; messageSizeLimit = 20000000;
# policydSPFExtraConfig = ''
# skip_addresses = 193.1.99.86/32
# '';
ldap = { ldap = {
enable = true; enable = true;
uris = cfg.ldap.hosts; uris = cfg.ldap.hosts;
@ -506,13 +444,13 @@ in {
searchScope = "sub"; searchScope = "sub";
dovecot = { dovecot = {
userFilter = "(skMail=%{user})"; userFilter = "(skMail=%u)";
# can lock down how much space each user has access to from ldap # can lock down how much space each user has access to from ldap
userAttrs = "quotaEmail=quota_rule=*:bytes=%$,=quota_rule2=Trash:storage=+100M"; userAttrs = "quotaEmail=quota_rule=*:bytes=%$,=quota_rule2=Trash:storage=+100M";
# accept emails in, but only allow access to paid up members # accept emails in, but only allow access to paid up members
passFilter = "(&(|${create_filter cfg.groups})(skMail=%{user}))"; passFilter = "(&(|${create_filter cfg.groups})(skMail=%u))";
}; };
postfix = { postfix = {
@ -528,60 +466,18 @@ in {
}; };
services.dovecot2.sieve.scripts = { services.dovecot2.sieve.scripts = {
before = sieveConfigFile; before = configFile;
};
# This is to add a bcc to outgoing mail
# this then interacts with teh filters to put it in the right folder
# we can directly add to the postfix service here
services.postfix = let
# mostly copied from the upstream mailserver config/functions
mappedFile = name: "hash:/var/lib/postfix/conf/${name}";
sender_bcc_maps_file = let
content = lookupTableToString create_skynet_service_bcc;
in
builtins.toFile "sender_bcc_maps" content;
lookupTableToString = attrs: let
valueToString = value: lib.concatStringsSep ", " value;
in
lib.concatStringsSep "\n" (lib.mapAttrsToList (name: value: "${name} ${valueToString value}") attrs);
# convert the mailboxes config to something that can be used here
create_skynet_email_bcc = mailbox: {
name = "${mailbox}@skynet.ie";
value = ["${mailbox}@skynet.ie"];
};
create_skynet_service_bcc = builtins.listToAttrs (map (mailbox: (create_skynet_email_bcc mailbox.account)) service_mailboxes);
in {
mapFiles."sender_bcc_maps" = sender_bcc_maps_file;
config = {
sender_bcc_maps = [
(mappedFile "sender_bcc_maps")
];
};
}; };
# tune the spam filter # tune the spam filter
services.rspamd.locals = { /*
"multimap.conf" = { services.rspamd.extraConfig = ''
text = '' actions {
IP_WHITELIST { reject = null; # Disable rejects, default is 15
type = "ip"; add_header = 7; # Add header when reaching this score
prefilter = true; greylist = 4; # Apply greylisting when reaching this score
map = "/etc/rspamd/local.d/ip_whitelist.map"; }
action = "accept"; '';
} */
'';
};
"ip_whitelist.map" = {
text = ''
193.1.99.86
'';
};
};
}; };
} }

View file

@ -6,17 +6,27 @@
... ...
}: }:
with lib; let with lib; let
name = "games"; cfg = config.services.skynet_games;
cfg = config.services.skynet."${name}";
in { in {
imports = [ imports = [
./dns.nix
./nginx.nix ./nginx.nix
./games/minecraft.nix ./games/minecraft.nix
]; ];
options.services.skynet."${name}" = { options.services.skynet_games = {
enable = mkEnableOption "Skynet Games"; enable = mkEnableOption "Skynet Games";
host = {
ip = mkOption {
type = types.str;
};
name = mkOption {
type = types.str;
};
};
domain = { domain = {
tld = mkOption { tld = mkOption {
type = types.str; type = types.str;
@ -36,20 +46,26 @@ in {
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
services.skynet.dns.records = [ skynet_dns.records = [
# need a base domain # need a base domain
{ {
record = cfg.domain.sub; record = cfg.domain.sub;
r_type = "CNAME"; r_type = "CNAME";
value = config.services.skynet.host.name; value = cfg.host.name;
} }
]; ];
services.skynet.acme.domains = [ skynet_acme.domains = [
"${cfg.domain.sub}.skynet.ie" "${cfg.domain.sub}.skynet.ie"
]; ];
services.nginx.virtualHosts = { services.nginx.virtualHosts = {
"${cfg.host.ip}" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/".return = "307 https://skynet.ie";
};
"${cfg.domain.sub}.skynet.ie" = { "${cfg.domain.sub}.skynet.ie" = {
forceSSL = true; forceSSL = true;
useACMEHost = "skynet"; useACMEHost = "skynet";
@ -58,9 +74,14 @@ in {
}; };
# the minecraft servers # the minecraft servers
services.skynet.games_minecraft = { services.skynet_games_minecraft = {
enable = true; enable = true;
host = {
ip = cfg.host.ip;
name = cfg.domain.sub;
};
domain = { domain = {
sub = "minecraft.${cfg.domain.sub}"; sub = "minecraft.${cfg.domain.sub}";
}; };

View file

@ -4,57 +4,181 @@
lib, lib,
inputs, inputs,
... ...
}: let }:
# function to create the cname record for eachs erver with lib; let
create_cname = configs: cfg = config.services.skynet_games_minecraft;
lib.lists.forEach configs (
c: {
record = "${c.address}.games";
r_type = "CNAME";
value = config.services.skynet.host.name;
}
);
# function to create the srv record # got tired of how long this is so I created a var for it.
# this allows us to change the port without impacting (java) users short_domain = "${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}";
create_srv = configs:
lib.lists.forEach configs (c: {
record = "_minecraft._tcp.${c.address}.games.skynet.ie.";
r_type = "SRV";
value = "0 10 ${c.port} ${config.services.skynet.host.name}.skynet.ie.";
});
servers = [
{
address = "minecraft.compsoc";
port = "25518";
}
{
address = "minecraft-classic.compsoc";
port = "25518";
}
{
address = "minecraft-aged.compsoc";
port = "25519";
}
{
address = "minecraft.gsoc";
port = "25521";
}
{
address = "minecraft.phildeb";
port = "25522";
}
{
address = "minecraft.anime";
port = "25523";
}
];
in { in {
imports = [ imports = [
../acme.nix
../dns.nix
../firewall.nix
../nginx.nix
inputs.arion.nixosModules.arion
]; ];
config = { options.services.skynet_games_minecraft = {
services.skynet.dns.records = (create_cname servers) ++ (create_srv servers); enable = mkEnableOption "Skynet Games Minecraft";
host = {
ip = mkOption {
type = types.str;
};
name = mkOption {
type = types.str;
};
};
domain = {
tld = mkOption {
type = types.str;
default = "ie";
};
base = mkOption {
type = types.str;
default = "skynet";
};
sub = mkOption {
type = types.str;
default = "minecraft.games";
};
};
};
config = mkIf cfg.enable {
skynet_firewall.forward = [
"ip daddr ${cfg.host.ip} tcp dport 80 counter packets 0 bytes 0 accept"
"ip daddr ${cfg.host.ip} tcp dport 443 counter packets 0 bytes 0 accept"
"ip daddr ${cfg.host.ip} tcp dport 25565 counter packets 0 bytes 0 accept"
];
skynet_acme.domains = [
"${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}"
"*.${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}"
];
skynet_dns.records = [
# the minecraft (web) config server
{
record = "config.${cfg.domain.sub}";
r_type = "CNAME";
value = cfg.host.name;
}
# our own minecraft hosts
{
record = "compsoc_classic.${cfg.domain.sub}";
r_type = "CNAME";
value = cfg.host.name;
}
{
record = "compsoc.${cfg.domain.sub}";
r_type = "CNAME";
value = cfg.host.name;
}
# gsoc servers
{
record = "gsoc.${cfg.domain.sub}";
r_type = "CNAME";
value = cfg.host.name;
}
{
record = "gsoc_abridged.${cfg.domain.sub}";
r_type = "CNAME";
value = cfg.host.name;
}
# phildeb
{
record = "phildeb.${cfg.domain.sub}";
r_type = "CNAME";
value = cfg.host.name;
}
];
networking.firewall.allowedTCPPorts = [
# for the proxy
25565
];
services.nginx.virtualHosts = {
"${cfg.host.ip}" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/".return = "307 https://skynet.ie";
};
# https://config.minecraft.games.skynet.ie
"config.${short_domain}" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/" = {
proxyPass = "https://localhost:8443";
proxyWebsockets = true;
};
};
# https://compsoc_classic.minecraft.games.skynet.ie/map/
"compsoc_classic.${short_domain}" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/map/".alias = "/etc/games/minecraft/craftycontrol/servers/f4c5eb33-c6d6-421c-81ab-ded31f6e8750/plugins/dynmap/web/";
};
};
# arion is one way to use docker on nixos
# see https://gitlab.com/c2842/computer_society/nixos/-/blob/733b867f4782afa795848135a83e97a5cafaf16a/applications/games/minecraft.nix
# for an example of a single compose file with multiple services
virtualisation.arion = {
backend = "docker";
projects = {
minecraft.settings.services = {
mc_proxy.service = {
image = "itzg/mc-router:1.18.0";
ports = ["25565:25565/tcp"];
expose = ["25565"];
command = [
"--mapping=compsoc_classic.${short_domain}=mc_config:20000,compsoc.${short_domain}=mc_config:20001,gsoc.${short_domain}=mc_config:20002,gsoc.${short_domain}=mc_config:20002,gsoc_abridged.${short_domain}=mc_config:20003,phildeb.${short_domain}=mc_config:20004"
];
};
mc_config.service = {
image = "registry.gitlab.com/crafty-controller/crafty-4:4.1.1";
environment = {
TZ = "Etc/UTC";
};
volumes = [
"/etc/games/minecraft/craftycontrol/backups:/crafty/backups"
"/etc/games/minecraft/craftycontrol/logs:/crafty/logs"
"/etc/games/minecraft/craftycontrol/servers:/crafty/servers"
"/etc/games/minecraft/craftycontrol/config:/crafty/app/config"
"/etc/games/minecraft/craftycontrol/import:/crafty/import"
];
ports = [
# this ius https only
"8443:8443/tcp"
# compsoc classic
"20000:20000/tcp"
# compsoc
"20001:20001/tcp"
# games
"20002:20002/tcp"
"20003:20003/tcp"
# phildeb
"20004:20004/tcp"
];
};
};
};
};
}; };
} }

View file

@ -1,139 +0,0 @@
{
config,
pkgs,
lib,
...
}:
with lib; let
name = "forgejo";
cfg = config.services.skynet."${name}";
domain_base = "${cfg.domain.base}.${cfg.domain.tld}";
domain_full = "${cfg.domain.sub}.${domain_base}";
in {
imports = [
];
options.services.skynet."${name}" = {
enable = mkEnableOption "Skynet Forgejo";
domain = {
tld = mkOption {
type = types.str;
default = "ie";
};
base = mkOption {
type = types.str;
default = "skynet";
};
sub = mkOption {
type = types.str;
default = name;
};
};
forgejo = {
port = mkOption {
type = types.port;
default = 3000;
};
};
};
config = mkIf cfg.enable {
# age.secrets.forgejo-mailer-password = {
# file = ../../secrets/forgejo/mailer-password.age;
# mode = "400";
# owner = "forgejo";
# };
services.skynet.acme.domains = [
"${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}"
];
# using https://nixos.org/manual/nixos/stable/index.html#module-services-gitlab as a guide
services.skynet.dns.records = [
{
record = cfg.domain.sub;
r_type = "CNAME";
value = config.services.skynet.host.name;
}
];
services.nginx.virtualHosts = {
# main site
"${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/" = {
proxyPass = "http://localhost:${toString cfg.forgejo.port}";
extraConfig = ''
add_header Content-Security-Policy "frame-ancestors 'self' https://silver.users.skynet.ie";
client_max_body_size 1000M;
'';
};
};
};
# for signing reasons
programs.gnupg.agent = {
enable = true;
enableSSHSupport = true;
};
services.forgejo = {
enable = true;
package = pkgs.forgejo;
database.type = "sqlite3";
# Enable support for Git Large File Storage
lfs.enable = true;
settings = {
server = {
DOMAIN = "${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}";
# You need to specify this to remove the port from URLs in the web UI.
ROOT_URL = "https://${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}/";
HTTP_PORT = cfg.forgejo.port;
};
# You can temporarily allow registration to create an admin user.
service.DISABLE_REGISTRATION = true;
# Add support for actions, based on act: https://github.com/nektos/act
actions = {
ENABLED = true;
DEFAULT_ACTIONS_URL = "github";
};
indexer = {
# Will consume more disk space, but we have plenty of that
REPO_INDEXER_ENABLED = true;
};
database = {
SQLITE_JOURNAL_MODE = "WAL";
};
# Allow for signing off merge requests
# "repository.signing" = {
# SIGNING_KEY = "5B2DED0FE9F8627A";
# SIGNING_NAME = "Skynet";
# SIGNING_EMAIL = "forgejo@glados.skynet.ie";
# MERGES = "always";
# };
# Sending emails is completely optional
# You can send a test email from the web UI at:
# Profile Picture > Site Administration > Configuration > Mailer Configuration
# mailer = {
# ENABLED = true;
# SMTP_ADDR = "mail.${cfg.domain.base}.${cfg.domain.tld}";
# FROM = "noreply@${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}";
# USER = "noreply@${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}";
# };
};
# mailerPasswordFile = config.age.secrets.forgejo-mailer-password.path;
};
};
}

View file

@ -1,161 +0,0 @@
{
config,
pkgs,
lib,
inputs,
...
}:
with lib; let
name = "forgejo_runner";
cfg = config.services.skynet."${name}";
in {
imports = [
];
options.services.skynet."${name}" = {
enable = mkEnableOption "Skynet ForgeJo Runner";
name = mkOption {
type = types.str;
default = config.networking.hostName;
};
website = mkOption {
default = "https://forgejo.skynet.ie";
type = types.str;
};
user = mkOption {
default = "gitea-runner";
type = types.str;
};
secret = mkOption {
type = types.path;
};
};
config = mkIf cfg.enable {
# https://search.nixos.org/options?from=0&size=50&sort=alpha_desc&type=packages&query=services.gitlab-runner.
environment.systemPackages = with pkgs; [
forgejo-actions-runner
];
age.secrets.forgejo_runner_token = {
file = cfg.secret;
owner = cfg.user;
group = cfg.user;
};
# make sure the ssh config stuff is in teh right palce
systemd.tmpfiles.rules = [
#"d /home/${cfg.user} 0755 ${cfg.user} ${cfg.user}"
"L+ /home/${cfg.user}/.ssh/config 0755 ${cfg.user} ${cfg.user} - ${./ssh_config}"
];
age.secrets.forgejo_runner_ssh = {
file = ../../secrets/forgejo/runners/ssh.age;
mode = "600";
owner = "${cfg.user}";
group = "${cfg.user}";
symlink = false;
path = "/home/${cfg.user}/.ssh/skynet/root";
};
nix = {
settings = {
trusted-users = [
# allow the runner to build nix stuff and to use the cache
"gitea-runner"
];
trusted-public-keys = [
"skynet-cache:zMFLzcRZPhUpjXUy8SF8Cf7KGAZwo98SKrzeXvdWABo="
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
];
substituters = [
"https://nix-cache.skynet.ie/skynet-cache/"
"https://cache.nixos.org/"
];
trusted-substituters = [
"https://nix-cache.skynet.ie/skynet-cache/"
"https://cache.nixos.org/"
];
};
};
# very basic setup to always be watching for changes in teh cache
systemd.services.attic-uploader = {
enable = true;
serviceConfig = {
ExecStart = "${pkgs.attic-client}/bin/attic watch-store skynet-cache";
User = "root";
Restart = "always";
RestartSec = 1;
};
};
# give teh runner user a home to store teh ssh config stuff
systemd.services.gitea-runner-default.serviceConfig = {
DynamicUser = lib.mkForce false;
User = lib.mkForce cfg.user;
};
users = {
groups."${cfg.user}" = {};
users."${cfg.user}" = {
#isSystemUser = true;
isNormalUser = true;
group = cfg.user;
createHome = true;
shell = pkgs.bash;
};
};
boot.kernel.sysctl."net.ipv4.ip_forward" = true; # 1
virtualisation.docker.enable = true;
# taken from https://github.com/NixOS/nixpkgs/issues/245365#issuecomment-1663854128
virtualisation.docker.listenOptions = ["/run/docker.sock" "127.0.0.1:2375"];
# the actual runner
services.gitea-actions-runner = {
package = pkgs.forgejo-actions-runner;
instances.default = {
enable = true;
name = cfg.name;
url = cfg.website;
tokenFile = config.age.secrets.forgejo_runner_token.path;
labels = [
## optionally provide native execution on the host:
"nix:host"
"docker:docker://node:22-bookworm"
"ubuntu-latest:docker://node:22-bookworm"
];
hostPackages = with pkgs; [
# default ones
bash
coreutils
curl
gawk
git
gnused
nodejs
wget
# useful to have in path
jq
which
dpkg
zip
git-lfs
# used in deployments
inputs.colmena.defaultPackage."x86_64-linux"
attic-client
lix
openssh
sudo
];
};
};
};
}

View file

@ -1,5 +0,0 @@
Host *.skynet.ie 193.1.99.* 193.1.96.165
User root
IdentityFile ~/.ssh/skynet/root
IdentitiesOnly yes

View file

@ -5,18 +5,31 @@
... ...
}: }:
with lib; let with lib; let
name = "gitlab"; cfg = config.services.skynet_gitlab;
cfg = config.services.skynet."${name}";
domain_base = "${cfg.domain.base}.${cfg.domain.tld}"; domain_base = "${cfg.domain.base}.${cfg.domain.tld}";
domain_full = "${cfg.domain.sub}.${domain_base}"; domain_full = "${cfg.domain.sub}.${domain_base}";
in { in {
imports = [ imports = [
./acme.nix
./dns.nix
./firewall.nix
./nginx.nix
]; ];
options.services.skynet."${name}" = { options.services.skynet_gitlab = {
enable = mkEnableOption "Skynet Gitlab"; enable = mkEnableOption "Skynet Gitlab";
host = {
ip = mkOption {
type = types.str;
};
name = mkOption {
type = types.str;
};
};
domain = { domain = {
tld = mkOption { tld = mkOption {
type = types.str; type = types.str;
@ -30,7 +43,7 @@ in {
sub = mkOption { sub = mkOption {
type = types.str; type = types.str;
default = name; default = "gitlab";
}; };
}; };
@ -56,54 +69,54 @@ in {
# grep -r --exclude-dir={docker,containers,log,sys,nix,proc} gitlab / # grep -r --exclude-dir={docker,containers,log,sys,nix,proc} gitlab /
age.secrets.gitlab_pw = { age.secrets.gitlab_pw = {
file = ../../secrets/gitlab/pw.age; file = ../secrets/gitlab/pw.age;
owner = cfg.user; owner = cfg.user;
group = cfg.user; group = cfg.user;
}; };
age.secrets.gitlab_secrets_db = { age.secrets.gitlab_secrets_db = {
file = ../../secrets/gitlab/secrets_db.age; file = ../secrets/gitlab/secrets_db.age;
owner = cfg.user; owner = cfg.user;
group = cfg.user; group = cfg.user;
}; };
age.secrets.gitlab_secrets_secret = { age.secrets.gitlab_secrets_secret = {
file = ../../secrets/gitlab/secrets_secret.age; file = ../secrets/gitlab/secrets_secret.age;
owner = cfg.user; owner = cfg.user;
group = cfg.user; group = cfg.user;
}; };
age.secrets.gitlab_secrets_otp = { age.secrets.gitlab_secrets_otp = {
file = ../../secrets/gitlab/secrets_otp.age; file = ../secrets/gitlab/secrets_otp.age;
owner = cfg.user; owner = cfg.user;
group = cfg.user; group = cfg.user;
}; };
age.secrets.gitlab_secrets_jws = { age.secrets.gitlab_secrets_jws = {
file = ../../secrets/gitlab/secrets_jws.age; file = ../secrets/gitlab/secrets_jws.age;
owner = cfg.user; owner = cfg.user;
group = cfg.user; group = cfg.user;
}; };
age.secrets.gitlab_db_pw = { age.secrets.gitlab_db_pw = {
file = ../../secrets/gitlab/db_pw.age; file = ../secrets/gitlab/db_pw.age;
owner = cfg.user; owner = cfg.user;
group = cfg.user; group = cfg.user;
}; };
services.skynet.acme.domains = [ skynet_acme.domains = [
"${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}" "${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}"
# Lets Encrypt seems to have a 4 levels limit for certs # Lets Encrypt seems to have a 4 levels limit for certs
"*.pages.${cfg.domain.base}.${cfg.domain.tld}" "*.pages.${cfg.domain.base}.${cfg.domain.tld}"
]; ];
# using https://nixos.org/manual/nixos/stable/index.html#module-services-gitlab as a guide # using https://nixos.org/manual/nixos/stable/index.html#module-services-gitlab as a guide
services.skynet.dns.records = [ skynet_dns.records = [
{ {
record = cfg.domain.sub; record = cfg.domain.sub;
r_type = "A"; r_type = "A";
value = config.services.skynet.host.ip; value = cfg.host.ip;
} }
# for gitlab pages # for gitlab pages
{ {
record = "*.pages.${cfg.domain.base}.${cfg.domain.tld}."; record = "*.pages.${cfg.domain.base}.${cfg.domain.tld}.";
r_type = "A"; r_type = "A";
value = config.services.skynet.host.ip; value = cfg.host.ip;
} }
# for email # for email
@ -113,7 +126,7 @@ in {
value = ''10 ${domain_full}.''; value = ''10 ${domain_full}.'';
} }
{ {
record = config.services.skynet.host.ip; record = cfg.host.ip;
r_type = "PTR"; r_type = "PTR";
value = "${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}."; value = "${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}.";
} }
@ -137,16 +150,17 @@ in {
services.openssh.ports = [22 2222]; services.openssh.ports = [22 2222];
services.nginx.virtualHosts = { services.nginx.virtualHosts = {
"${cfg.host.ip}" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/".return = "307 https://skynet.ie";
};
# main site # main site
"${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}" = { "${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}" = {
forceSSL = true; forceSSL = true;
useACMEHost = "skynet"; useACMEHost = "skynet";
locations."/" = { locations."/".proxyPass = "http://unix:/run/gitlab/gitlab-workhorse.socket";
proxyPass = "http://unix:/run/gitlab/gitlab-workhorse.socket";
extraConfig = ''
client_max_body_size 1000M;
'';
};
}; };
# pages # pages
@ -244,7 +258,7 @@ in {
# default for pages is set to 8090 but that leaves an "ugly" port in the url, # default for pages is set to 8090 but that leaves an "ugly" port in the url,
# override it here to make it look good # override it here to make it look good
port = 80; port = 80;
#external_http = ["${config.services.skynet.host.ip}:80"]; #external_http = ["${cfg.host.ip}:80"];
}; };
}; };
}; };

View file

@ -0,0 +1,121 @@
{
config,
pkgs,
lib,
...
}:
with lib; let
cfg = config.services.skynet_gitlab_runner;
in {
imports = [
];
options.services.skynet_gitlab_runner = {
enable = mkEnableOption "Skynet Gitlab Runner";
runner = {
name = mkOption {
type = types.str;
};
gitlab = mkOption {
default = "https://gitlab.skynet.ie";
type = types.str;
};
description = mkOption {
default = cfg.runner.name;
type = types.str;
};
docker = {
image = mkOption {
default = "alpine:3.18.4";
type = types.str;
};
cleanup_dates = mkOption {
# https://man.archlinux.org/man/systemd.time.7#CALENDAR_EVENTS
# it will use a lot of storage so clear it daily, may change to hourly if required
default = "daily";
type = types.str;
};
};
};
};
config = mkIf cfg.enable {
# https://search.nixos.org/options?from=0&size=50&sort=alpha_desc&type=packages&query=services.gitlab-runner.
environment.systemPackages = [
pkgs.gitlab-runner
];
age.secrets.runner_01_nix.file = ../secrets/gitlab/runners/runner01.age;
age.secrets.runner_02_general.file = ../secrets/gitlab/runners/runner02.age;
boot.kernel.sysctl."net.ipv4.ip_forward" = true; # 1
virtualisation.docker.enable = true;
# taken from https://github.com/NixOS/nixpkgs/issues/245365#issuecomment-1663854128
virtualisation.docker.listenOptions = ["/run/docker.sock" "127.0.0.1:2375"];
services.gitlab-runner = {
enable = true;
# clear-docker-cache = {
# enable = true;
# dates = cfg.runner.docker.cleanup_dates;
# };
services = {
# might make a function later to have multiple runners, might never need it though
runner_nix = {
cloneUrl = cfg.runner.gitlab;
description = "For Nix only";
registrationFlags = ["--docker-host" "tcp://127.0.0.1:2375"];
registrationConfigFile = config.age.secrets.runner_01_nix.path;
dockerImage = cfg.runner.docker.image;
# from https://nixos.wiki/wiki/Gitlab_runner
dockerVolumes = [
"/nix/store:/nix/store:ro"
"/nix/var/nix/db:/nix/var/nix/db:ro"
"/nix/var/nix/daemon-socket:/nix/var/nix/daemon-socket:ro"
];
dockerDisableCache = true;
preBuildScript = pkgs.writeScript "setup-container" ''
mkdir -p -m 0755 /nix/var/log/nix/drvs
mkdir -p -m 0755 /nix/var/nix/gcroots
mkdir -p -m 0755 /nix/var/nix/profiles
mkdir -p -m 0755 /nix/var/nix/temproots
mkdir -p -m 0755 /nix/var/nix/userpool
mkdir -p -m 1777 /nix/var/nix/gcroots/per-user
mkdir -p -m 1777 /nix/var/nix/profiles/per-user
mkdir -p -m 0755 /nix/var/nix/profiles/per-user/root
mkdir -p -m 0700 "$HOME/.nix-defexpr"
. ${pkgs.nix}/etc/profile.d/nix-daemon.sh
${pkgs.nix}/bin/nix-channel --add https://nixos.org/channels/nixos-unstable nixpkgs # 3
${pkgs.nix}/bin/nix-channel --update nixpkgs
${pkgs.nix}/bin/nix-env -i ${concatStringsSep " " (with pkgs; [nix cacert git openssh])}
'';
environmentVariables = {
ENV = "/etc/profile";
USER = "root";
NIX_REMOTE = "daemon";
PATH = "/nix/var/nix/profiles/default/bin:/nix/var/nix/profiles/default/sbin:/bin:/sbin:/usr/bin:/usr/sbin";
NIX_SSL_CERT_FILE = "/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt";
};
tagList = ["nix"];
};
runner_general = {
cloneUrl = cfg.runner.gitlab;
description = "General Runner";
registrationFlags = ["--docker-host" "tcp://127.0.0.1:2375"];
registrationConfigFile = config.age.secrets.runner_02_general.path;
dockerImage = cfg.runner.docker.image;
};
};
};
};
}

View file

@ -1,81 +0,0 @@
{
lib,
config,
...
}:
with lib; let
name = "grafana";
cfg = config.services.skynet."${name}";
port = 4444;
in {
imports = [
];
options.services.skynet."${name}" = {
enable = mkEnableOption "Grafana Server";
datasource = {
name = mkOption {
type = types.str;
};
url = mkOption {
type = types.str;
};
};
};
config = mkIf cfg.enable {
services.skynet.dns.records = [
{
record = "${name}";
r_type = "CNAME";
value = config.services.skynet.host.name;
}
];
services.skynet.acme.domains = [
"${name}.skynet.ie"
];
age.secrets.grafana_pw = {
file = ../secrets/grafana/pw.age;
owner = "grafana";
group = "grafana";
};
services.grafana = {
enable = true;
domain = "${name}.skynet.ie";
port = port;
settings.server.root_url = "https://${name}.skynet.ie";
settings.security.admin_password = "$__file{${config.age.secrets.grafana_pw.path}}";
provision = {
enable = true;
datasources.settings.datasources = [
{
name = "Prometheus";
type = "prometheus";
url = "http://localhost:${toString config.services.skynet.prometheus.server.port}";
isDefault = true;
editable = true;
}
];
};
};
services.nginx.virtualHosts = {
"${name}.skynet.ie" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/" = {
proxyPass = "http://localhost:${toString port}";
proxyWebsockets = true;
};
};
};
};
}

View file

@ -6,18 +6,30 @@
... ...
}: }:
with lib; let with lib; let
name = "ldap_backend"; cfg = config.services.ldap_backend;
cfg = config.services.skynet."${name}";
port_backend = "8087"; port_backend = "8087";
in { in {
imports = [ imports = [
../acme.nix
../dns.nix
../nginx.nix
inputs.skynet_ldap_backend.nixosModule."x86_64-linux" inputs.skynet_ldap_backend.nixosModule."x86_64-linux"
../../config/users.nix ../../config/users.nix
]; ];
options.services.skynet."${name}" = { options.services.ldap_backend = {
enable = mkEnableOption "Skynet LDAP backend server"; enable = mkEnableOption "Skynet LDAP backend server";
host = {
ip = mkOption {
type = types.str;
};
name = mkOption {
type = types.str;
};
};
domain = { domain = {
tld = mkOption { tld = mkOption {
type = types.str; type = types.str;
@ -40,18 +52,19 @@ in {
#backups = [ "/etc/silver_ul_ical/database.db" ]; #backups = [ "/etc/silver_ul_ical/database.db" ];
age.secrets.ldap_details.file = ../../secrets/ldap/details.age; age.secrets.ldap_details.file = ../../secrets/ldap/details.age;
age.secrets.ldap_discord.file = ../../secrets/discord/ldap.age;
age.secrets.ldap_mail.file = ../../secrets/email/details.age; age.secrets.ldap_mail.file = ../../secrets/email/details.age;
age.secrets.ldap_wolves.file = ../../secrets/wolves/details.age; age.secrets.ldap_wolves.file = ../../secrets/wolves/details.age;
services.skynet.acme.domains = [ skynet_acme.domains = [
"${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}" "${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}"
]; ];
services.skynet.dns.records = [ skynet_dns.records = [
{ {
record = cfg.domain.sub; record = cfg.domain.sub;
r_type = "CNAME"; r_type = "CNAME";
value = config.services.skynet.host.name; value = cfg.host.name;
} }
]; ];
@ -61,13 +74,13 @@ in {
locations."/".proxyPass = "http://localhost:${port_backend}"; locations."/".proxyPass = "http://localhost:${port_backend}";
}; };
# this got imported
services.skynet_ldap_backend = { services.skynet_ldap_backend = {
enable = true; enable = true;
# contains teh password in env form # contains teh password in env form
env = { env = {
ldap = config.age.secrets.ldap_details.path; ldap = config.age.secrets.ldap_details.path;
discord = config.age.secrets.ldap_discord.path;
mail = config.age.secrets.ldap_mail.path; mail = config.age.secrets.ldap_mail.path;
wolves = config.age.secrets.ldap_wolves.path; wolves = config.age.secrets.ldap_wolves.path;
}; };

View file

@ -5,8 +5,7 @@
... ...
}: }:
with lib; let with lib; let
name = "ldap_client"; cfg = config.services.skynet_ldap_client;
cfg = config.services.skynet."${name}";
# always ensure the admin group has access # always ensure the admin group has access
create_filter_check_admin = x: create_filter_check_admin = x:
@ -28,9 +27,9 @@ in {
imports = []; imports = [];
# give users access to this server # give users access to this server
#services.skynet.ldap_client.groups = ["skynet-users-linux"]; #services.skynet_ldap_client.groups = ["skynet-users-linux"];
options.services.skynet."${name}" = { options.services.skynet_ldap_client = {
# options that need to be passed in to make this work # options that need to be passed in to make this work
enable = mkEnableOption "Skynet LDAP client"; enable = mkEnableOption "Skynet LDAP client";

View file

@ -9,19 +9,32 @@ Gonna use a priper nixos module for this
... ...
}: }:
with lib; let with lib; let
name = "ldap"; cfg = config.services.skynet_ldap;
cfg = config.services.skynet."${name}";
domain = "${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}"; domain = "${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}";
in { in {
# these are needed for teh program in question # these are needed for teh program in question
imports = [ imports = [
../acme.nix
../dns.nix
../nginx.nix
./backend.nix
]; ];
options.services.skynet."${name}" = { options.services.skynet_ldap = {
# options that need to be passed in to make this work # options that need to be passed in to make this work
enable = mkEnableOption "Skynet LDAP service"; enable = mkEnableOption "Skynet LDAP service";
host = {
ip = mkOption {
type = types.str;
};
name = mkOption {
type = types.str;
};
};
domain = { domain = {
tld = mkOption { tld = mkOption {
type = types.str; type = types.str;
@ -51,6 +64,13 @@ in {
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
# passthrough to the backend
services.ldap_backend = {
enable = true;
host.ip = cfg.host.ip;
host.name = cfg.host.name;
};
# after changing teh password openldap.service has to be restarted # after changing teh password openldap.service has to be restarted
age.secrets.ldap_pw = { age.secrets.ldap_pw = {
file = ../../secrets/ldap/pw.age; file = ../../secrets/ldap/pw.age;
@ -59,15 +79,15 @@ in {
group = "openldap"; group = "openldap";
}; };
services.skynet.acme.domains = [ skynet_acme.domains = [
domain domain
]; ];
services.skynet.dns.records = [ skynet_dns.records = [
{ {
record = cfg.domain.sub; record = cfg.domain.sub;
r_type = "CNAME"; r_type = "CNAME";
value = config.services.skynet.host.name; value = cfg.host.name;
} }
]; ];

View file

@ -5,16 +5,28 @@
... ...
}: }:
with lib; let with lib; let
name = "nextcloud"; cfg = config.services.skynet_nextcloud;
cfg = config.services.skynet."${name}";
domain = "${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}"; domain = "${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}";
in { in {
imports = [ imports = [
./acme.nix
./dns.nix
./nginx.nix
]; ];
options.services.skynet."${name}" = { options.services.skynet_nextcloud = {
enable = mkEnableOption "Skynet Nextcloud"; enable = mkEnableOption "Skynet Nextcloud";
host = {
ip = mkOption {
type = types.str;
};
name = mkOption {
type = types.str;
};
};
domain = { domain = {
tld = mkOption { tld = mkOption {
type = types.str; type = types.str;
@ -28,7 +40,7 @@ in {
sub = mkOption { sub = mkOption {
type = types.str; type = types.str;
default = name; default = "nextcloud";
}; };
}; };
}; };
@ -42,27 +54,21 @@ in {
group = "nextcloud"; group = "nextcloud";
}; };
services.skynet.acme.domains = [ skynet_acme.domains = [
domain domain
"onlyoffice.${domain}" "onlyoffice.${domain}"
"whiteboard.${domain}"
]; ];
services.skynet.dns.records = [ skynet_dns.records = [
{ {
record = cfg.domain.sub; record = cfg.domain.sub;
r_type = "CNAME"; r_type = "CNAME";
value = config.services.skynet.host.name; value = cfg.host.name;
} }
{ {
record = "onlyoffice.${cfg.domain.sub}"; record = "onlyoffice.${cfg.domain.sub}";
r_type = "CNAME"; r_type = "CNAME";
value = config.services.skynet.host.name; value = cfg.host.name;
}
{
record = "whiteboard.${cfg.domain.sub}";
r_type = "CNAME";
value = config.services.skynet.host.name;
} }
]; ];
@ -70,7 +76,7 @@ in {
services.nextcloud = { services.nextcloud = {
enable = true; enable = true;
package = pkgs.nextcloud30; package = pkgs.nextcloud28;
hostName = domain; hostName = domain;
https = true; https = true;
@ -84,10 +90,9 @@ in {
appstoreEnable = true; appstoreEnable = true;
extraApps = { extraApps = with config.services.nextcloud.package.packages.apps; {
inherit (config.services.nextcloud.package.packages.apps) richdocuments; inherit forms groupfolders maps notes onlyoffice polls;
}; };
extraAppsEnable = true;
settings = { settings = {
trusted_proxies = ["193.1.99.65"]; trusted_proxies = ["193.1.99.65"];
@ -97,23 +102,17 @@ in {
}; };
}; };
environment.etc."nextcloud-whiteboard-secret".text = '' nixpkgs.config.allowUnfree = true;
JWT_SECRET_KEY=test123 services.onlyoffice = {
'';
services.nextcloud-whiteboard-server = {
enable = true; enable = true;
settings.NEXTCLOUD_URL = "https://nextcloud.skynet.ie";
secrets = ["/etc/nextcloud-whiteboard-secret"];
}; };
nixpkgs.config.allowUnfree = true;
# impacted by https://github.com/NixOS /nixpkgs/issues/352443
# services.onlyoffice = {
# enable = true;
# };
services.nginx.virtualHosts = { services.nginx.virtualHosts = {
"${cfg.host.ip}" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/".return = "307 https://skynet.ie";
};
${domain} = { ${domain} = {
forceSSL = true; forceSSL = true;
useACMEHost = "skynet"; useACMEHost = "skynet";
@ -123,14 +122,6 @@ in {
useACMEHost = "skynet"; useACMEHost = "skynet";
locations."/".proxyPass = "http://127.0.0.1:8000"; locations."/".proxyPass = "http://127.0.0.1:8000";
}; };
"whiteboard.${domain}" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/" = {
proxyPass = "http://localhost:3002";
proxyWebsockets = true;
};
};
}; };
}; };
} }

View file

@ -9,6 +9,8 @@
recommendedGzipSettings = true; recommendedGzipSettings = true;
recommendedProxySettings = true; recommendedProxySettings = true;
statusPage = true;
# give Nginx access to our certs # give Nginx access to our certs
group = "acme"; group = "acme";
}; };

View file

@ -1,98 +0,0 @@
/*
A nix cache for our use
atticd-atticadm make-token --sub "admin_username" --validity "10y" --pull "*" --push "*" --create-cache "*" --delete "*" --configure-cache "*" --configure-cache-retention "*" --destroy-cache "*"
# for the gitlab runner, done eyarly
atticd-atticadm make-token --sub "wheatly-runner" --validity "1y" --pull "skynet-cache" --push "skynet-cache"
Documentation:
https://docs.attic.rs/introduction.html
*/
{
lib,
config,
pkgs,
...
}:
with lib; let
name = "nix-cache";
cfg = config.services.skynet."${name}";
in {
imports = [
];
options.services.skynet."${name}" = {
enable = mkEnableOption "Skynet Nix Cache";
};
config = mkIf cfg.enable {
services.skynet.acme.domains = [
"${name}.skynet.ie"
];
services.skynet.dns.records = [
{
record = "${name}";
r_type = "CNAME";
value = config.services.skynet.host.name;
}
];
users.groups."nix-serve" = {};
users.users."nix-serve" = {
isSystemUser = true;
group = "nix-serve";
};
services.atticd = {
enable = true;
# Replace with absolute path to your credentials file
environmentFile = "/etc/atticd.env";
settings = {
listen = "127.0.0.1:8080";
# Data chunking
#
# Warning: If you change any of the values here, it will be
# difficult to reuse existing chunks for newly-uploaded NARs
# since the cutpoints will be different. As a result, the
# deduplication ratio will suffer for a while after the change.
chunking = {
# The minimum NAR size to trigger chunking
#
# If 0, chunking is disabled entirely for newly-uploaded NARs.
# If 1, all NARs are chunked.
nar-size-threshold = 64 * 1024; # 64 KiB
# The preferred minimum size of a chunk, in bytes
min-size = 16 * 1024; # 16 KiB
# The preferred average size of a chunk, in bytes
avg-size = 64 * 1024; # 64 KiB
# The preferred maximum size of a chunk, in bytes
max-size = 256 * 1024; # 256 KiB
};
};
};
networking.firewall.allowedTCPPorts = [80 443];
services.nginx = {
clientMaxBodySize = "500m";
virtualHosts = {
"${name}.skynet.ie" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/" = {
proxyPass = "http://127.0.0.1:8080";
};
};
};
};
};
}

View file

@ -1,17 +0,0 @@
# Open Governance
Started by DCU this is an initiative to make the running of (computer) societies more open and resilient.
The goal is to back these up in multiple locations.
| Uni | Tag | Repo | Notes |
|-----|----------|----------------------------------------------------------|-------|
| DCU | redbrick | https://github.com/redbrick/open-governance | |
| UL | skynet | https://gitlab.skynet.ie/compsoc1/compsoc/open-goverance | |
| | | | |
## Keys
We host our own keyserver: https://keyserver.skynet.ie
Use it in commands like so:
``gpg --keyserver hkp://keyserver.skynet.ie:80 --send-key KEY_ID``

View file

@ -1,62 +0,0 @@
/*
This file is for hosting teh open governance for other societies
*/
{
lib,
config,
pkgs,
...
}:
with lib; let
name = "keyserver";
cfg = config.services.skynet."${name}";
port = 11371;
in {
imports = [
];
options.services.skynet."${name}" = {
enable = mkEnableOption "Skynet Public Keyserver";
};
config = mkIf cfg.enable {
services.skynet.acme.domains = [
"${name}.skynet.ie"
];
services.skynet.dns.records = [
{
record = "${name}";
r_type = "CNAME";
value = config.services.skynet.host.name;
}
];
services.hockeypuck = {
enable = true;
port = port;
};
# hockeypuck needs a database backend
services.postgresql = {
enable = true;
ensureDatabases = ["hockeypuck"];
ensureUsers = [
{
name = "hockeypuck";
ensureDBOwnership = true;
}
];
};
services.nginx.virtualHosts = {
"${name}.skynet.ie" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/" = {
proxyPass = "http://localhost:${toString port}";
};
};
};
};
}

View file

@ -1,61 +0,0 @@
/*
This file is for hosting teh open governance for other societies
*/
{
lib,
config,
pkgs,
...
}:
with lib; let
# - instead of _ for dns reasons
name = "open-governance";
cfg = config.services.skynet."${name}";
folder = "/var/skynet/${name}";
in {
imports = [
];
options.services.skynet."${name}" = {
enable = mkEnableOption "Skynet Open Governance";
};
config = {
services.skynet.acme.domains = [
"${name}.skynet.ie"
];
services.skynet.dns.records = [
{
record = "${name}";
r_type = "CNAME";
value = config.services.skynet.host.name;
}
];
# create a folder to store the archives
systemd.tmpfiles.rules = [
"d ${folder} 0755 ${config.services.nginx.user} ${config.services.nginx.group}"
"L+ ${folder}/README.md - - - - ${./README.md}"
];
services.nginx.virtualHosts = {
"${name}.skynet.ie" = {
forceSSL = true;
useACMEHost = "skynet";
root = folder;
locations = {
"/".extraConfig = "autoindex on;";
# show md files as plain text
"~ \.md".extraConfig = ''
types {
text/plain md;
}
'';
};
};
};
};
}

View file

@ -1,6 +0,0 @@
# Notes on Pelican
## Panel
* ``pelican-install`` is in env that can be used to isntall
* then go to ``panel-address.skynet.ie/installer`` to finish the setup

View file

@ -1,30 +0,0 @@
{
pkgs,
dir,
}:
pkgs.writeShellScriptBin "pelican-install" ''
DIR=${dir}
echo "Installing Pelican panel to $DIR ..."
if [ -d $DIR ]; then
echo "Directory $DIR already exists, exiting"
exit 1
fi
echo "Creating directory ..."
mkdir -p $DIR
cd $DIR
echo "Downloading Pelican panel ..."
curl -L https://github.com/pelican-dev/panel/releases/latest/download/panel.tar.gz | tar -xzv
echo "Installing Pelican panel using composer ..."
yes | composer install --no-dev --optimize-autoloader
echo "Setting up the environment ..."
yes "" | php artisan p:environment:setup
echo "Setting permissions ..."
chmod -R 755 storage/* bootstrap/cache/
chown -R nginx:acme $DIR
echo "Pelican panel installed successfully"
''

View file

@ -1,48 +0,0 @@
{
pkgs,
dir,
}:
pkgs.writeShellScriptBin "pelican-update" ''
DIR=${dir}
echo "Updateing Pelican panel in $DIR ..."
if [ -d $DIR ]; then
echo "Directory $DIR found, entering maintenance mode ..."
else
echo "Directory $DIR does not exist, exiting"
exit 1
fi
cd $DIR
php artisan down
echo "Downloading Pelican panel update ..."
curl -L https://github.com/pelican-dev/panel/releases/latest/download/panel.tar.gz | tar -xzv
echo "Setting permissions ..."
chmod -R 755 storage/* bootstrap/cache
echo "Updating Pelican panel using composer ..."
yes | composer install --no-dev --optimize-autoloader
echo "Clearing compiled template cache ..."
php artisan view:clear
php artisan config:clear
echo "Optimizing Pelican panel ..."
php artisan filament:optimize
echo "Updating the database ..."
php artisan migrate --seed --force
echo "Setting permissions ..."
chown -R nginx:acme $DIR
echo "Restart Pelican queue service ..."
systemctl restart pelican-queue.service
echo "Exiting maintenance mode ..."
php artisan up
echo "Pelican panel updated successfully"
''

View file

@ -1,24 +0,0 @@
{
stdenv,
lib,
fetchurl,
docker,
gnutar,
}:
stdenv.mkDerivation rec {
pname = "pelican-wings";
version = "v1.0.0-beta9";
src = fetchurl {
url = "https://github.com/pelican-dev/wings/releases/download/${version}/wings_linux_amd64";
hash = "sha256-YaS1bthNSeWXH5drc2yensRqsRAOa2VXvivJOaPybqc=";
};
buildInputs = [docker gnutar];
phases = ["installPhase"];
installPhase = ''
install -D $src $out/bin/wings
'';
}

View file

@ -1,323 +0,0 @@
{
inputs,
pkgs,
lib,
config,
...
}:
with lib; let
name = "pelican";
cfg = config.services.skynet."${name}";
php_pool = name;
domain_panel = "${cfg.panel.domain.sub}.${cfg.panel.domain.base}.${cfg.panel.domain.tld}";
packages = let
dir = cfg.panel.dir;
in [
pkgs.curl
pkgs.gnutar
pkgs.unzip
pkgs.gzip
pkgs.php83
pkgs.php83Packages.composer
pkgs.php83Extensions.gd
pkgs.php83Extensions.mysqli
pkgs.php83Extensions.mbstring
pkgs.php83Extensions.bcmath
pkgs.php83Extensions.xml
pkgs.php83Extensions.curl
pkgs.php83Extensions.zip
pkgs.php83Extensions.intl
pkgs.php83Extensions.sqlite3
(import ./pelican-panel-update.nix {
inherit pkgs;
inherit dir;
})
];
in {
imports = [
];
options.services.skynet."${name}" = {
panel = {
enable = mkEnableOption "Pelican Panel";
dir = mkOption {
type = types.str;
default = "/var/lib/pelican_panel";
};
domain = {
tld = mkOption {
type = types.str;
default = "ie";
};
base = mkOption {
type = types.str;
default = "skynet";
};
sub = mkOption {
type = types.str;
#default = name;
default = "panel.games";
};
};
};
wing = {
enable = mkEnableOption "Pelican Wing";
node_name = mkOption {
type = types.str;
};
};
};
config = mkMerge [
(mkIf cfg.panel.enable {
services.skynet.acme.domains = [
domain_panel
];
# using https://nixos.org/manual/nixos/stable/index.html#module-services-gitlab as a guide
services.skynet.dns.records = [
{
record = cfg.panel.domain.sub;
r_type = "CNAME";
value = config.services.skynet.host.name;
}
];
environment.systemPackages = packages;
systemd.timers."pelican-cron" = {
wantedBy = ["timers.target"];
timerConfig = {
OnBootSec = "5m";
OnUnitActiveSec = "1m";
Unit = "pelican-cron.service";
};
};
systemd.services."pelican-cron" = {
script = ''
${pkgs.php83}/bin/php ${cfg.panel.dir}/artisan schedule:run >> /dev/null 2>&1
'';
serviceConfig = {
Type = "oneshot";
};
};
systemd.services.pelican-queue = {
wantedBy = ["multi-user.target"];
serviceConfig = {
User = config.services.nginx.user;
Group = config.services.nginx.group;
Restart = "always";
ExecStart = "${pkgs.php83}/bin/php -q ${cfg.panel.dir}/artisan queue:work --tries=3";
startLimitInterval = 180;
startLimitBurst = 30;
RestartSec = "5";
};
};
systemd.services.pelican-panel-setup = {
wantedBy = ["pelican-queue.target" "pelican-cron.target"];
partOf = [];
path = packages;
serviceConfig = {
Type = "oneshot";
User = "root";
Group = "root";
TimeoutSec = "infinity";
Restart = "on-failure";
RemainAfterExit = true;
ExecStart = pkgs.writeShellScript "pelican-panel-install" ''
DIR=${cfg.panel.dir}
echo "Installing Pelican panel to $DIR ..."
if [ -d $DIR ]; then
echo "Directory $DIR already exists, exiting"
exit 1
fi
echo "Creating directory ..."
mkdir -p $DIR
cd $DIR
echo "Downloading Pelican panel ..."
curl -L https://github.com/pelican-dev/panel/releases/latest/download/panel.tar.gz | tar -xzv
echo "Installing Pelican panel using composer ..."
yes | composer install --no-dev --optimize-autoloader
echo "Setting up the environment ..."
yes "" | php artisan p:environment:setup
echo "Setting permissions ..."
chmod -R 755 storage/* bootstrap/cache/
chown -R ${config.services.nginx.user}:${config.services.nginx.group} $DIR
echo "Pelican panel installed successfully"
'';
};
};
services.phpfpm.pools.${php_pool} = {
user = config.services.nginx.user;
group = config.services.nginx.group;
settings = {
"listen.owner" = config.services.nginx.user;
"listen.group" = config.services.nginx.group;
"listen.mode" = "0600";
"pm" = "dynamic";
"pm.max_children" = 75;
"pm.start_servers" = 10;
"pm.min_spare_servers" = 5;
"pm.max_spare_servers" = 20;
"pm.max_requests" = 500;
"catch_workers_output" = 1;
};
};
services.nginx.virtualHosts."${domain_panel}" = {
root = "${cfg.panel.dir}/public";
forceSSL = true;
useACMEHost = "skynet";
extraConfig = ''
index index.html index.htm index.php;
charset utf-8;
access_log off;
error_log /var/log/nginx/pelican.app-error.log error;
client_max_body_size 100m;
client_body_timeout 120s;
sendfile off;
ssl_session_cache shared:SSL:10m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
ssl_prefer_server_ciphers on;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
add_header Content-Security-Policy "frame-ancestors 'self'";
add_header X-Frame-Options DENY;
add_header Referrer-Policy same-origin;
'';
locations = {
"/" = {
extraConfig = ''
try_files $uri $uri/ /index.php?$query_string;
'';
};
"/favicon.ico".extraConfig = ''
access_log off;
log_not_found off;
'';
"/robots.txt".extraConfig = ''
access_log off;
log_not_found off;
'';
"~ \\.php$" = {
extraConfig = ''
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:${config.services.phpfpm.pools.${php_pool}.socket};
fastcgi_index index.php;
include ${config.services.nginx.package}/conf/fastcgi_params;
fastcgi_param PHP_VALUE "upload_max_filesize = 100M \n post_max_size=100M";
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTP_PROXY "";
fastcgi_intercept_errors off;
fastcgi_buffer_size 16k;
fastcgi_buffers 4 16k;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
'';
};
"~ /\\.ht".extraConfig = ''
deny all;
'';
};
};
})
(mkIf cfg.wing.enable {
services.skynet.acme.domains = [
"${cfg.wing.node_name}.${domain_panel}"
];
# using https://nixos.org/manual/nixos/stable/index.html#module-services-gitlab as a guide
services.skynet.dns.records = [
{
record = "${cfg.wing.node_name}.${cfg.panel.domain.sub}";
r_type = "CNAME";
value = config.services.skynet.host.name;
}
];
services.nginx.virtualHosts = {
"${cfg.wing.node_name}.${domain_panel}" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/".proxyPass = "http://127.0.0.1:8080";
};
};
networking.firewall.allowedTCPPorts = [8080 8443];
virtualisation.docker.enable = true;
environment.systemPackages = [
(pkgs.callPackage ./pelican-wing-package.nix {})
];
users.groups.pelican = {};
users.users.pelican = {
#createHome = true;
isSystemUser = true;
#home = "/etc/pelican";
group = "pelican";
extraGroups = ["docker" "acme"];
# X11 is to ensure the directory can be traversed
#homeMode = "711";
};
systemd.services.pelican-wings = {
description = "Wings Daemon";
after = ["docker.service"];
requires = ["docker.service"];
partOf = ["docker.service"];
serviceConfig = {
User = "root";
WorkingDirectory = "/etc/pelican";
LimitNOFILE = 4096;
PIDFile = "/var/run/wings/daemon.pid";
ExecStart = "/run/current-system/sw/bin/wings";
Restart = "on-failure";
startLimitInterval = 180;
startLimitBurst = 30;
RestartSec = "5";
};
wantedBy = ["multi-user.target"];
};
systemd.tmpfiles.rules = [
"L+ /etc/letsencrypt/live/${cfg.wing.node_name}.${domain_panel}/fullchain.pem - pelican acme - /var/lib/acme/skynet/fullchain.pem"
"L+ /etc/letsencrypt/live/${cfg.wing.node_name}.${domain_panel}/privkey.pem - pelican acme - /var/lib/acme/skynet/key.pem"
];
})
];
}

View file

@ -1,95 +0,0 @@
{
nodes,
lib,
config,
...
}:
with lib; let
name = "prometheus";
cfg = config.services.skynet."${name}";
# dont have to worry about any external addresses for this
# create a list of either "ip@port" or ""
# the ""s then get filtered out by filter_empty
exporters = {
dns = (
lib.attrsets.mapAttrsToList (
key: value:
if value.config.services.skynet.dns.server.enable
then "${value.config.deployment.targetHost}:${toString value.config.services.prometheus.exporters.bind.port}"
else ""
)
nodes
);
node = lib.attrsets.mapAttrsToList (key: value: "${value.config.deployment.targetHost}:${toString value.config.services.prometheus.exporters.node.port}") nodes;
};
# clears any invalid entries
filter_empty = inputs: (builtins.filter (value: value != "") inputs);
in {
imports = [];
options.services.skynet."${name}" = {
server = {
enable = mkEnableOption "Prometheus Server";
port = mkOption {
type = types.port;
default = 9001;
};
};
external = {
node = mkOption {
type = types.listOf types.str;
default = [];
description = ''
To add other nodes outside of nix, specify ip and port that server should listen to here
'';
};
};
ports = {
node = mkOption {
type = types.port;
default = 9100;
};
};
};
config = mkMerge [
{
services.prometheus.exporters.node = {
enable = true;
port = cfg.ports.node;
openFirewall = true;
# most collectors are on by default see https://github.com/prometheus/node_exporter for more options
enabledCollectors = ["systemd" "processes"];
};
}
(mkIf cfg.server.enable {
services.prometheus = {
enable = true;
port = cfg.server.port;
scrapeConfigs = [
{
job_name = "node_exporter";
static_configs = [
{
targets = filter_empty (exporters.node ++ cfg.external.node);
}
];
}
{
job_name = "bind";
static_configs = [
{
targets = filter_empty exporters.dns;
}
];
}
];
};
})
];
}

View file

@ -0,0 +1,93 @@
/*
Once https://github.com/NixOS/nixpkgs/pull/267764 is merged this can be removed
*/
{
config,
pkgs,
lib,
...
}:
with lib; {
options.proxmoxLXC = {
enable = mkOption {
default = true;
type = types.bool;
description = lib.mdDoc "Whether to enable the ProxmoxLXC.";
};
privileged = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
Whether to enable privileged mounts
'';
};
manageNetwork = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
Whether to manage network interfaces through nix options
When false, systemd-networkd is enabled to accept network
configuration from proxmox.
'';
};
manageHostName = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
Whether to manage hostname through nix options
When false, the hostname is picked up from /etc/hostname
populated by proxmox.
'';
};
};
config = let
cfg = config.proxmoxLXC;
in
mkIf cfg.enable {
system.build.tarball = pkgs.callPackage ../../lib/make-system-tarball.nix {
storeContents = [
{
object = config.system.build.toplevel;
symlink = "none";
}
];
contents = [
{
source = config.system.build.toplevel + "/init";
target = "/sbin/init";
}
];
extraCommands = "mkdir -p root etc/systemd/network";
};
boot = {
isContainer = true;
loader.initScript.enable = true;
};
networking = mkIf (!cfg.manageNetwork) {
useDHCP = false;
useHostResolvConf = false;
useNetworkd = true;
# pick up hostname from /etc/hostname generated by proxmox
hostName = mkIf (!cfg.manageHostName) (mkForce "");
};
services.openssh = {
enable = mkDefault true;
startWhenNeeded = mkDefault true;
};
systemd.mounts =
mkIf (!cfg.privileged)
[
{
where = "/sys/kernel/debug";
enable = false;
}
];
};
}

View file

@ -7,8 +7,7 @@
... ...
}: }:
with lib; let with lib; let
name = "backup"; cfg = config.services.skynet_backup;
cfg = config.services.skynet."${name}";
enable_client = cfg.normal.backups != null && cfg.normal.backups != []; enable_client = cfg.normal.backups != null && cfg.normal.backups != [];
@ -38,24 +37,22 @@ with lib; let
ownServers = builtins.listToAttrs (builtins.concatLists ( ownServers = builtins.listToAttrs (builtins.concatLists (
lib.attrsets.mapAttrsToList ( lib.attrsets.mapAttrsToList (
key: value: let key: value: let
backup = value.config.services.skynet.backup; backup = value.config.services.skynet_backup;
backup_host = value.config.services.skynet.host;
in in
if if
( (
(builtins.hasAttr "backup" value.config.services.skynet) (builtins.hasAttr "skynet_backup" value.config.services)
&& backup.server.enable && backup.server.enable
# chgeck that its not itself && backup.host.name != cfg.host.name
&& backup_host.name != config.services.skynet.host.name
&& !backup.server.appendOnly && !backup.server.appendOnly
) )
then [ then [
{ {
name = backup_host.name; name = backup.host.name;
value = value =
base base
// { // {
repositoryFile = "/etc/skynet/restic/${backup_host.name}"; repositoryFile = "/etc/skynet/restic/${backup.host.name}";
backupPrepareCommand = '' backupPrepareCommand = ''
#!${pkgs.stdenv.shell} #!${pkgs.stdenv.shell}
@ -66,13 +63,13 @@ with lib; let
mkdir -p $baseDir mkdir -p $baseDir
cd $baseDir cd $baseDir
echo -n "rest:http://root:password@${backup_host.ip}:${toString backup.server.port}/root/${config.services.skynet.host.name}" > ${backup_host.name} echo -n "rest:http://root:password@${backup.host.ip}:${toString backup.server.port}/root/${cfg.host.name}" > ${backup.host.name}
# read in teh password # read in teh password
#PW = `cat ${config.age.secrets.restic.path}` #PW = `cat ${config.age.secrets.restic.path}`
line=$(head -n 1 ${config.age.secrets.restic.path}) line=$(head -n 1 ${config.age.secrets.restic.path})
sed -i "s/password/$line/g" ${backup_host.name} sed -i "s/password/$line/g" ${backup.host.name}
''; '';
}; };
} }
@ -88,8 +85,9 @@ in {
# using https://github.com/greaka/ops/blob/818be4c4dea9129abe0f086d738df4cb0bb38288/apps/restic/options.nix as a base # using https://github.com/greaka/ops/blob/818be4c4dea9129abe0f086d738df4cb0bb38288/apps/restic/options.nix as a base
# https://git.hrnz.li/Ulli/nixos/src/commit/5edca2dfdab3ce52208e4dfd2b92951e500f8418/profiles/server/restic.nix # https://git.hrnz.li/Ulli/nixos/src/commit/5edca2dfdab3ce52208e4dfd2b92951e500f8418/profiles/server/restic.nix
# will eb enabled on every server # will eb enabled on every server
options.services.skynet."${name}" = { options.services.skynet_backup = {
enable = mkEnableOption "Skynet backup"; # backup is enabled by default
# enable = mkEnableOption "Skynet backup";
# what folders to backup # what folders to backup
normal = { normal = {
@ -129,6 +127,16 @@ in {
}; };
}; };
host = {
ip = mkOption {
type = types.str;
};
name = mkOption {
type = types.str;
};
};
server = { server = {
enable = mkEnableOption "Skynet backup Server"; enable = mkEnableOption "Skynet backup Server";
@ -144,15 +152,14 @@ in {
}; };
}; };
config = mkMerge [ config =
{ {
# these values are anabled for every client # these values are anabled for every client
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
restic restic
]; ];
} }
// mkIf cfg.server.enable {
(mkIf cfg.server.enable {
networking.firewall.allowedTCPPorts = [ networking.firewall.allowedTCPPorts = [
cfg.server.port cfg.server.port
]; ];
@ -168,13 +175,12 @@ in {
services.restic.server = { services.restic.server = {
enable = true; enable = true;
listenAddress = "${config.services.skynet.host.ip}:${toString cfg.server.port}"; listenAddress = "${cfg.host.ip}:${toString cfg.server.port}";
appendOnly = cfg.server.appendOnly; appendOnly = cfg.server.appendOnly;
privateRepos = true; privateRepos = true;
}; };
}) }
// mkIf enable_client {
(mkIf enable_client {
# client stuff here # client stuff here
# A list of all login accounts. To create the password hashes, use # A list of all login accounts. To create the password hashes, use
@ -183,17 +189,15 @@ in {
age.secrets.restic.file = ../secrets/backup/restic.age; age.secrets.restic.file = ../secrets/backup/restic.age;
services.restic.backups = mkMerge [ services.restic.backups =
ownServers ownServers
{ // {
# merge teh two configs together # merge teh two configs together
# backblaze = base // { # backblaze = base // {
# # backupos for each server are stored in a folder under their name # # backupos for each server are stored in a folder under their name
# repository = "b2:NixOS-Main2:/${config.services.skynet.host.name}"; # repository = "b2:NixOS-Main2:/${cfg.host.name}";
# #environmentFile = config.age.secrets.backblaze.path; # #environmentFile = config.age.secrets.backblaze.path;
# }; # };
} };
]; };
})
];
} }

108
applications/skynet.ie.nix Normal file
View file

@ -0,0 +1,108 @@
{
config,
pkgs,
lib,
inputs,
...
}:
with lib; let
cfg = config.services.skynet;
in {
imports = [
./acme.nix
./dns.nix
];
options.services.skynet = {
host = {
ip = mkOption {
type = types.str;
};
name = mkOption {
type = types.str;
};
};
};
config = {
skynet_acme.domains = [
# the root one is already covered by teh certificate
"2016.skynet.ie"
"discord.skynet.ie"
"public.skynet.ie"
"renew.skynet.ie"
];
skynet_dns.records = [
# means root domain, so skynet.ie
{
record = "@";
r_type = "A";
value = cfg.host.ip;
}
{
record = "2016";
r_type = "CNAME";
value = cfg.host.name;
}
{
record = "discord";
r_type = "CNAME";
value = cfg.host.name;
}
{
record = "public";
r_type = "CNAME";
value = cfg.host.name;
}
{
record = "renew";
r_type = "CNAME";
value = cfg.host.name;
}
];
networking.firewall.allowedTCPPorts = [80 443];
services.nginx = {
enable = true;
group = "acme";
virtualHosts = {
# main site
"skynet.ie" = {
forceSSL = true;
useACMEHost = "skynet";
root = "${inputs.skynet_website.defaultPackage."x86_64-linux"}";
};
# archive of teh site as it was ~2012 to 2016
"2016.skynet.ie" = {
forceSSL = true;
useACMEHost = "skynet";
root = "${inputs.skynet_website_2016.defaultPackage."x86_64-linux"}";
};
# a custom discord url, because we are too cheap otehrwise
"discord.skynet.ie" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/".return = "307 https://discord.gg/mkuKJkCuyM";
};
"public.skynet.ie" = {
forceSSL = true;
useACMEHost = "skynet";
root = "${inputs.compsoc_public.packages.x86_64-linux.default}";
locations."/".extraConfig = "autoindex on;";
};
# for alumni members to renew their account
"renew.skynet.ie" = {
forceSSL = true;
useACMEHost = "skynet";
root = "${inputs.skynet_website_renew.defaultPackage."x86_64-linux"}";
};
};
};
};
}

View file

@ -1,52 +0,0 @@
{year}: {
config,
pkgs,
lib,
inputs,
...
}:
with lib; {
imports = [];
config = {
services.skynet.dns.records = [
{
record = year;
r_type = "CNAME";
value = config.services.skynet.host.name;
}
];
services.nginx = {
virtualHosts = {
"${year}.skynet.ie" = {
forceSSL = true;
useACMEHost = "skynet";
root = "${inputs."skynet_website_${year}".defaultPackage."x86_64-linux"}";
# Handle any of the old php sites
# https://stackoverflow.com/a/21911610
locations = {
"/" = {
index = "index.html index.htm index.php";
tryFiles = "$uri $uri.html $uri/ @extensionless-php";
};
"~ \\.php$" = {
extraConfig = ''
fastcgi_pass unix:${config.services.phpfpm.pools.old_sites.socket};
fastcgi_index index.php;
'';
tryFiles = "$uri =404";
};
"@extensionless-php" = {
extraConfig = ''
rewrite ^(.*)$ $1.php last;
'';
};
};
};
};
};
};
}

View file

@ -1,134 +0,0 @@
{
config,
pkgs,
lib,
inputs,
...
}:
with lib; let
name = "website";
cfg = config.services.skynet."${name}";
in {
imports = [
# import in past website versions, available at $year.skynet.ie
# at teh end of teh year add it here
(import ./old_site.nix {year = "2024";})
(import ./old_site.nix {year = "2023";})
(import ./old_site.nix {year = "2022";})
(import ./old_site.nix {year = "2016";})
(import ./old_site.nix {year = "2006";})
(import ./old_site.nix {year = "2003";})
(import ./old_site.nix {year = "1996";})
];
options.services.skynet."${name}" = {
enable = mkEnableOption "Skynet Main Website";
};
config = mkIf cfg.enable {
services.skynet.acme.domains = [
"*.skynet.ie"
"*.discord.skynet.ie"
];
services.skynet.dns.records = [
# means root domain, so skynet.ie
{
record = "@";
r_type = "A";
value = config.services.skynet.host.ip;
}
{
record = "www";
r_type = "CNAME";
value = config.services.skynet.host.name;
}
{
record = "discord";
r_type = "CNAME";
value = config.services.skynet.host.name;
}
{
record = "wolves";
r_type = "CNAME";
value = config.services.skynet.host.name;
}
{
record = "public";
r_type = "CNAME";
value = config.services.skynet.host.name;
}
{
record = "*.discord";
r_type = "CNAME";
value = config.services.skynet.host.name;
}
];
services.nginx = {
virtualHosts = let
main_site = {
forceSSL = true;
useACMEHost = "skynet";
locations = {
"/".root = "${inputs.skynet_website.defaultPackage."x86_64-linux"}";
# this redirects old links to new format
"~* ~(?<username>[a-z_0-9]*)(?<files>\\S*)$" = {
priority = 1;
return = "307 https://$username.users.skynet.ie$files";
};
};
};
in {
# main site
"www.skynet.ie" = main_site;
"skynet.ie" = main_site;
"wolves.skynet.ie" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/".return = "307 https://ulwolves.ie/society/computer";
};
# a custom discord url, because we are too cheap otehrwise
"discord.skynet.ie" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/".return = "307 https://discord.gg/mkuKJkCuyM";
};
"compsoc.discord.skynet.ie" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/".return = "307 https://discord.gg/mkuKJkCuyM";
};
"committee.discord.skynet.ie" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/".return = "307 https://discord.gg/D6mbASJKxU";
};
"public.skynet.ie" = {
forceSSL = true;
useACMEHost = "skynet";
root = "${inputs.compsoc_public.packages.x86_64-linux.default}";
locations."/".extraConfig = "autoindex on;";
};
};
};
# Some old sites need a php pool running
services.phpfpm.pools.old_sites = {
user = "nobody";
settings = {
"pm" = "dynamic";
"listen.owner" = config.services.nginx.user;
"pm.max_children" = 5;
"pm.start_servers" = 2;
"pm.min_spare_servers" = 1;
"pm.max_spare_servers" = 3;
"pm.max_requests" = 500;
};
};
};
}

View file

@ -1,59 +0,0 @@
{
config,
pkgs,
lib,
inputs,
...
}:
with lib; let
name = "wiki";
cfg = config.services.skynet."${name}";
in {
imports = [
];
options.services.skynet."${name}" = {
enable = mkEnableOption "Skynet Wiki";
};
config = mkIf cfg.enable {
services.skynet.dns.records = [
{
record = "renew";
r_type = "CNAME";
value = config.services.skynet.host.name;
}
{
record = "wiki";
r_type = "CNAME";
value = config.services.skynet.host.name;
}
];
services.nginx = {
virtualHosts = {
"wiki.skynet.ie" = {
forceSSL = true;
useACMEHost = "skynet";
root = "${inputs.skynet_website_wiki.defaultPackage."x86_64-linux"}";
# https://stackoverflow.com/a/38238001/11964934
extraConfig = ''
location / {
if ($request_uri ~ ^/(.*)\.html) {
return 302 /$1;
}
try_files $uri $uri.html $uri/ =404;
}
'';
};
# redirect old links to the new wiki
"renew.skynet.ie" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/".return = "307 https://wiki.skynet.ie";
};
};
};
};
}

View file

@ -6,42 +6,30 @@
... ...
}: }:
with lib; let with lib; let
name = "website_users"; cfg = config.services.skynet_users;
cfg = config.services.skynet."${name}"; in {
php_pool = name; imports = [
./acme.nix
./dns.nix
./nginx.nix
];
custom = domain: user: { options.services.skynet_users = {
"${domain}" = { host = {
forceSSL = true; ip = mkOption {
enableACME = true; type = types.str;
locations = { };
"/" = { name = mkOption {
alias = "/home/${user}/public_html/"; type = types.str;
index = "index.html";
extraConfig = ''
autoindex on;
'';
tryFiles = "$uri$args $uri$args/ /index.html";
};
}; };
}; };
}; };
in {
imports = [
];
options.services.skynet."${name}" = {
enable = mkEnableOption "Skynet User Linux Server";
};
config = { config = {
# we havea more limited ports range on the skynet server # ssh access
services.skynet.prometheus.ports = {
node = 9000;
};
# allow more than admins access # allow more than admins access
services.skynet.ldap_client = { services.skynet_ldap_client = {
groups = [ groups = [
"skynet-admins-linux" "skynet-admins-linux"
"skynet-users-linux" "skynet-users-linux"
@ -49,21 +37,21 @@ in {
}; };
# Website config # Website config
services.skynet.acme.domains = [ skynet_acme.domains = [
"users.skynet.ie" "users.skynet.ie"
"*.users.skynet.ie" "*.users.skynet.ie"
]; ];
services.skynet.dns.records = [ skynet_dns.records = [
{ {
record = "users"; record = "users";
r_type = "CNAME"; r_type = "CNAME";
value = config.services.skynet.host.name; value = cfg.host.name;
} }
{ {
record = "*.users"; record = "*.users";
r_type = "CNAME"; r_type = "CNAME";
value = config.services.skynet.host.name; value = cfg.host.name;
} }
]; ];
@ -81,66 +69,32 @@ in {
# normally services cannot read home dirs # normally services cannot read home dirs
systemd.services.nginx.serviceConfig.ProtectHome = "read-only"; systemd.services.nginx.serviceConfig.ProtectHome = "read-only";
systemd.services."phpfpm-${php_pool}".serviceConfig.ProtectHome = lib.mkForce "read-only";
services.phpfpm.pools.${php_pool} = { services.nginx.virtualHosts = {
user = config.services.nginx.user; "${cfg.host.ip}" = {
group = config.services.nginx.group; forceSSL = true;
settings = { useACMEHost = "skynet";
"listen.owner" = config.services.nginx.user; locations."/".return = "307 https://skynet.ie";
"pm" = "dynamic";
"pm.max_children" = 32;
"pm.max_requests" = 500;
"pm.start_servers" = 2;
"pm.min_spare_servers" = 2;
"pm.max_spare_servers" = 5;
"php_admin_value[error_log]" = "stderr";
"php_admin_flag[log_errors]" = true;
"catch_workers_output" = true;
}; };
phpEnv."PATH" = lib.makeBinPath [pkgs.php];
};
services.nginx.virtualHosts = lib.mkMerge [
# main site # main site
{ "*.users.skynet.ie" = {
"*.users.skynet.ie" = { forceSSL = true;
forceSSL = true; useACMEHost = "skynet";
useACMEHost = "skynet"; serverName = "~^(?<user>.+)\.users\.skynet\.ie";
serverName = "~^(?<user>.+)\.users\.skynet\.ie";
# username.users.skynet.ie/ # username.users.skynet.ie/
# user goes: # user goes:
# chmod 711 ~ # chmod 711 ~
# chmod -R 755 ~/public_html # chmod -R 755 ~/public_html
locations = { locations."/" = {
"/" = { alias = "/home/$user/public_html/";
alias = "/home/$user/public_html/"; index = "index.html";
index = "index.html"; extraConfig = "autoindex on;";
extraConfig = '' tryFiles = "$uri$args $uri$args/ /index.html";
autoindex on;
'';
tryFiles = "$uri$args $uri$args/ /index.html";
};
"~ ^(.+\\.php)(.*)$" = {
root = "/home/$user/public_html/";
index = "index.php";
extraConfig = ''
autoindex on;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:${config.services.phpfpm.pools.${php_pool}.socket};
include ${pkgs.nginx}/conf/fastcgi.conf;
'';
tryFiles = "$uri$args $uri$args/ /index.php";
};
};
}; };
} };
};
(custom "outinul.ie" "outinul")
(custom "www.outinul.ie" "outinul")
];
}; };
} }

View file

@ -1,77 +0,0 @@
{
lib,
config,
...
}:
with lib; let
name = "sso";
cfg = config.services.skynet."${name}";
in {
imports = [
];
options.services.skynet."${name}" = {
enable = mkEnableOption "Keycloak server";
datasource = {
name = mkOption {
type = types.str;
};
url = mkOption {
type = types.str;
};
};
};
config = mkIf cfg.enable {
services.skynet.dns.records = [
{
record = "${name}";
r_type = "CNAME";
value = config.services.skynet.host.name;
}
];
services.skynet.acme.domains = [
"${name}.skynet.ie"
];
age.secrets.keycloak_pw.file = ../secrets/keycloak/pw.age;
services.nginx.virtualHosts = {
"${name}.skynet.ie" = {
forceSSL = true;
useACMEHost = "skynet";
locations = {
"/" = {
proxyPass = "http://localhost:${toString config.services.keycloak.settings.http-port}/";
};
};
};
};
services.postgresql.enable = true;
services.keycloak = {
enable = true;
initialAdminPassword = "sharky_loves_sso";
database = {
type = "postgresql";
createLocally = true;
username = "keycloak";
passwordFile = config.age.secrets.keycloak_pw.path;
};
settings = {
hostname = "${name}.skynet.ie";
http-port = 38080;
proxy-headers = "xforwarded";
http-enabled = true;
};
};
};
}

View file

@ -5,15 +5,28 @@
... ...
}: }:
with lib; let with lib; let
name = "ulfm"; cfg = config.services.skynet_ulfm;
cfg = config.services.skynet."${name}";
in { in {
imports = [ imports = [
./acme.nix
./dns.nix
./firewall.nix
./nginx.nix
]; ];
options.services.skynet."${name}" = { options.services.skynet_ulfm = {
enable = mkEnableOption "ULFM service"; enable = mkEnableOption "ULFM service";
host = {
ip = mkOption {
type = types.str;
};
name = mkOption {
type = types.str;
};
};
domain = { domain = {
tld = mkOption { tld = mkOption {
type = types.str; type = types.str;
@ -40,22 +53,22 @@ in {
8000 8000
]; ];
services.skynet.acme.domains = [ skynet_acme.domains = [
"${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}" "${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}"
]; ];
services.skynet.dns.records = [ skynet_dns.records = [
{ {
record = cfg.domain.sub; record = cfg.domain.sub;
r_type = "CNAME"; r_type = "CNAME";
value = config.services.skynet.host.name; value = cfg.host.name;
} }
]; ];
skynet_firewall.forward = [ skynet_firewall.forward = [
"ip daddr ${config.services.skynet.host.ip} tcp dport 80 counter packets 0 bytes 0 accept" "ip daddr ${cfg.host.ip} tcp dport 80 counter packets 0 bytes 0 accept"
"ip daddr ${config.services.skynet.host.ip} tcp dport 443 counter packets 0 bytes 0 accept" "ip daddr ${cfg.host.ip} tcp dport 443 counter packets 0 bytes 0 accept"
"ip daddr ${config.services.skynet.host.ip} tcp dport 8000 counter packets 0 bytes 0 accept" "ip daddr ${cfg.host.ip} tcp dport 8000 counter packets 0 bytes 0 accept"
]; ];
users.groups."icecast" = {}; users.groups."icecast" = {};
@ -81,12 +94,20 @@ in {
}; };
services.nginx = { services.nginx = {
enable = true;
group = "acme";
virtualHosts = { virtualHosts = {
"${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}" = { "${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}" = {
forceSSL = true; forceSSL = true;
useACMEHost = "skynet"; useACMEHost = "skynet";
locations."/".proxyPass = "http://localhost:8000"; locations."/".proxyPass = "http://localhost:8000";
}; };
"${cfg.host.ip}" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/".return = "307 https://skynet.ie";
};
}; };
}; };
}; };

View file

@ -1,70 +1,58 @@
{lib, ...}: { {lib, ...}: {
imports = [ imports = [];
];
options.skynet.records = lib.mkOption { options.skynet = {
description = "Records, sorted based on therir type"; records = lib.mkOption {
type = lib.types.listOf (lib.types.submodule (import ../applications/dns/options-records.nix { description = "Records, sorted based on therir type";
inherit lib; type = lib.types.attrsOf (lib.types.listOf (lib.types.submodule (import ../_types/dns_object.nix {
})); inherit lib;
})));
};
}; };
config = { config = {
skynet.records = skynet.records = {
[ "skynet.ie" = [
# Proxmox hosts
{ {
record = "jarvis"; record = "optimus-reborn";
r_type = "A"; r_type = "A";
value = "193.1.99.73"; value = "193.1.99.90";
server = true; server = true;
} }
{ {
record = "ultron"; record = "panel.games";
r_type = "A"; r_type = "CNAME";
value = "193.1.99.84"; value = "optimus-reborn";
server = true;
} }
# wifi in server room
{ {
record = "ash"; record = "bumblebee";
r_type = "A"; r_type = "A";
value = "193.1.99.114"; value = "193.1.99.91";
server = true; server = true;
} }
{ {
record = "mimi"; record = "minecraft.compsoc.games";
r_type = "A"; r_type = "CNAME";
value = "193.1.99.86"; value = "bumblebee";
server = true;
} }
{ {
record = "nuked"; record = "_minecraft._tcp.minecraft.compsoc.games.skynet.ie.";
r_type = "CNAME"; r_type = "SRV";
value = "neuromancer.skynet.ie."; value = "0 10 25518 minecraft.compsoc.games.skynet.ie.";
}
]
# non skynet domains
++ [
{
domain = "conradcollins.net";
record = "www";
r_type = "CNAME";
value = "skynet.skynet.ie.";
}
{
domain = "edelharty.net";
record = "www";
r_type = "CNAME";
value = "skynet.skynet.ie.";
}
{
domain = "damienconroy.com";
record = "www";
r_type = "CNAME";
value = "skynet.skynet.ie.";
} }
]; ];
# some space to avoid conflicts
"conradcollins.net" = [];
"edelharty.net" = [];
"outinul.ie" = [
{
record = "@";
r_type = "CNAME";
value = "users.skynet.ie.";
}
];
};
}; };
} }

View file

@ -1,11 +1,6 @@
{ {lib, ...}:
lib,
config,
...
}:
with lib; let with lib; let
port_backend = "8087"; port_backend = "8087";
cfg = config.skynet.users;
in { in {
options.skynet = { options.skynet = {
users = { users = {
@ -49,55 +44,34 @@ in {
config.skynet = { config.skynet = {
users = { users = {
committee = lib.lists.unique ( committee = [
# Committee - Core "silver"
[ "eoghanconlon73"
# President "sidhiel"
"silver" "maksimsger1"
# Secretary "kaiden"
"kaiden" "pine"
# Treasurer "nanda"
"peace" "sourabh1805"
# PRO "kronsy"
"amymucko" "skyapples"
# HSO ];
"skyapples"
]
# Committee - OCM
++ [
"connormc"
"cordlesscoder"
"dca_"
"eliza"
"emilyrutai"
"generically"
"mysticwolf"
"nanda"
"rituk_0817"
"sania_m"
"shourjyo24_"
"sunny"
"tatabbyi"
"wormyworm5"
]
# Committee - SISTEM
++ []
# Admins are part of Committee as well
++ cfg.admin
);
admin = [ admin = [
"silver" "silver"
"evanc" "evanc"
"eoghanconlon73"
"eliza" "eliza"
"esy"
]; ];
trainee = []; trainee = [
"milan"
"esy"
"kronsy"
];
lifetime = []; lifetime = [];
banned = []; banned = [];
clubs_societies = [ clubs_societies = [
"outinul" "outinul"
"gamesdev"
]; ];
restricted = restricted =

1344
flake.lock generated

File diff suppressed because it is too large Load diff

137
flake.nix
View file

@ -12,64 +12,78 @@
agenix.url = "github:ryantm/agenix"; agenix.url = "github:ryantm/agenix";
arion.url = "github:hercules-ci/arion"; arion.url = "github:hercules-ci/arion";
alejandra = { alejandra = {
url = "github:kamadorueda/alejandra"; url = "github:kamadorueda/alejandra/3.0.0";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
colmena.url = "github:zhaofengli/colmena";
# we host our own # email
# simple-nixos-mailserver.url = "gitlab:simple-nixos-mailserver/nixos-mailserver";
simple-nixos-mailserver = { simple-nixos-mailserver = {
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
url = "git+https://forgejo.skynet.ie/Skynet/misc_nixos-mailserver"; type = "gitlab";
host = "gitlab.skynet.ie";
owner = "compsoc1%2Fskynet";
repo = "misc%2Fnixos-mailserver";
}; };
###################### # account.skynet.ie
### skynet backend ### skynet_ldap_backend = {
###################### type = "gitlab";
skynet_ldap_backend.url = "git+https://forgejo.skynet.ie/Skynet/ldap_backend"; host = "gitlab.skynet.ie";
# skynet_ldap_backend.url = "git+file:/_college/CompSoc/Skynet/ldap_backend?shallow=1"; owner = "compsoc1%2Fskynet";
skynet_ldap_frontend.url = "git+https://forgejo.skynet.ie/Skynet/ldap_frontend"; repo = "ldap%2Fbackend";
skynet_website_wiki.url = "git+https://forgejo.skynet.ie/Skynet/wiki"; };
skynet_website_games.url = "git+https://forgejo.skynet.ie/Skynet/website_games"; skynet_ldap_frontend = {
skynet_discord_bot.url = "git+https://forgejo.skynet.ie/Skynet/discord-bot"; type = "gitlab";
skynet_discord_bot_t-800.url = "git+https://forgejo.skynet.ie/Skynet/discord-bot-t-800"; host = "gitlab.skynet.ie";
# for testing a local build owner = "compsoc1%2Fskynet";
# skynet_discord_bot.url = "git+file:/_college/CompSoc/Skynet/discord_bot?shallow=1"; repo = "ldap%2Ffrontend";
};
##################### skynet_website = {
### compsoc stuff ### type = "gitlab";
##################### host = "gitlab.skynet.ie";
compsoc_public.url = "git+https://forgejo.skynet.ie/Computer_Society/presentations_compsoc"; owner = "compsoc1%2Fskynet";
repo = "website%2F2023";
################# };
### skynet.ie ### skynet_website_2016 = {
################# type = "gitlab";
host = "gitlab.skynet.ie";
# this should always point to teh current website owner = "compsoc1%2Fskynet";
skynet_website.url = "git+https://forgejo.skynet.ie/Skynet/website_2023"; repo = "website%2F2016";
};
# past versions of the current website skynet_website_renew = {
skynet_website_2024.url = "git+https://forgejo.skynet.ie/Skynet/website_2023?ref=main&rev=8987e33cb709e7f2c30017e77edf9161b87d9885"; type = "gitlab";
skynet_website_2023.url = "git+https://forgejo.skynet.ie/Skynet/website_2023?ref=main&rev=c4d61c753292bf73ed41b47b1607cfc92a82a191"; host = "gitlab.skynet.ie";
skynet_website_2022.url = "git+https://forgejo.skynet.ie/Skynet/website_2023?ref=2022&rev=687a0b1811987cfc27c2e6f5a625c4d59ef577c2"; owner = "compsoc1%2Fskynet";
repo = "website%2Falumni-renew";
skynet_website_2016.url = "git+https://forgejo.skynet.ie/Skynet/website_2016"; };
skynet_website_2006.url = "git+https://forgejo.skynet.ie/Skynet/website_2006"; skynet_website_games = {
skynet_website_2003.url = "git+https://forgejo.skynet.ie/Skynet/website_2003"; type = "gitlab";
skynet_website_1996.url = "git+https://forgejo.skynet.ie/Skynet/website_1996"; host = "gitlab.skynet.ie";
owner = "compsoc1%2Fskynet";
repo = "website%2Fgames.skynet.ie";
};
skynet_discord_bot = {
type = "gitlab";
host = "gitlab.skynet.ie";
owner = "compsoc1%2Fskynet";
repo = "discord-bot";
};
compsoc_public = {
type = "gitlab";
host = "gitlab.skynet.ie";
owner = "compsoc1%2Fcompsoc";
repo = "presentations%2Fpresentations";
};
}; };
nixConfig = { nixConfig.bash-prompt-suffix = "[Skynet Dev] ";
extra-substituters = "https://nix-cache.skynet.ie/skynet-cache";
extra-trusted-public-keys = "skynet-cache:zMFLzcRZPhUpjXUy8SF8Cf7KGAZwo98SKrzeXvdWABo=";
};
outputs = { outputs = {
self, self,
nixpkgs, nixpkgs,
agenix, agenix,
alejandra, alejandra,
colmena,
... ...
} @ inputs: let } @ inputs: let
pkgs = nixpkgs.legacyPackages.x86_64-linux.pkgs; pkgs = nixpkgs.legacyPackages.x86_64-linux.pkgs;
@ -77,36 +91,24 @@
formatter.x86_64-linux = alejandra.defaultPackage."x86_64-linux"; formatter.x86_64-linux = alejandra.defaultPackage."x86_64-linux";
devShells.x86_64-linux.default = pkgs.mkShell { devShells.x86_64-linux.default = pkgs.mkShell {
name = "Skynet"; name = "Skynet build env";
nativeBuildInputs = [ nativeBuildInputs = [
pkgs.buildPackages.git pkgs.buildPackages.git
colmena.defaultPackage."x86_64-linux" pkgs.buildPackages.colmena
pkgs.attic-client
pkgs.buildPackages.nmap pkgs.buildPackages.nmap
]; ];
buildInputs = [agenix.packages.x86_64-linux.default]; buildInputs = [agenix.packages.x86_64-linux.default];
shellHook = ''export PROMPT_DIRTRIM=3; export PS1="[Skynet] \w:\$ "''; shellHook = ''export EDITOR="${pkgs.nano}/bin/nano --nonewlines"; unset LD_LIBRARY_PATH;'';
}; };
colmena = { colmena = {
meta = { meta = {
nixpkgs = import nixpkgs { nixpkgs = import nixpkgs {
system = "x86_64-linux"; system = "x86_64-linux";
overlays = [ overlays = [];
(final: prev: {
inherit
(final.lixPackageSets.stable)
nixpkgs-review
nix-direnv
nix-eval-jobs
nix-fast-build
colmena
;
})
];
}; };
specialArgs = { specialArgs = {
inherit inputs self; inherit inputs;
}; };
}; };
@ -125,6 +127,9 @@
# icecast - ULFM # icecast - ULFM
galatea = import ./machines/galatea.nix; galatea = import ./machines/galatea.nix;
# Game host
optimus = import ./machines/optimus.nix;
# LDAP host # LDAP host
kitt = import ./machines/kitt.nix; kitt = import ./machines/kitt.nix;
@ -151,18 +156,6 @@
# trainee server # trainee server
marvin = import ./machines/marvin.nix; marvin = import ./machines/marvin.nix;
# Public Services
calculon = import ./machines/calculon.nix;
# metrics
ariia = import ./machines/ariia.nix;
# games server - panel
optimus = import ./machines/optimus.nix;
# games server - host
bumblebee = import ./machines/bumblebee.nix;
}; };
}; };
} }

View file

@ -11,14 +11,24 @@ with lib; let
cfg = config.skynet; cfg = config.skynet;
in { in {
imports = [ imports = [
# This is required for LXC to function properly # custom lxc mocule until the patch gets merged in
(modulesPath + "/virtualisation/proxmox-lxc.nix") ../applications/proxmox-lxc.nix
# (modulesPath + "/virtualisation/proxmox-lxc.nix")
# for the secrets # for the secrets
inputs.agenix.nixosModules.default inputs.agenix.nixosModules.default
# base application config for all servers # every sever may need the firewall config stuff
../applications/_base.nix ../applications/firewall.nix
# every sever needs to have a dns record
../applications/dns.nix
# every server needs teh ldap client for admins
../applications/ldap/client.nix
# every server will need the config to backup to
../applications/restic.nix
]; ];
options.skynet = { options.skynet = {
@ -32,13 +42,7 @@ in {
config = { config = {
# if its a lxc enable # if its a lxc enable
proxmoxLXC = { proxmoxLXC.enable = cfg.lxc;
enable = cfg.lxc;
manageNetwork = true;
manageHostName = true;
};
age.secrets.root_pw.file = ../secrets/base/root_pass.age;
nix = { nix = {
settings = { settings = {
@ -57,10 +61,10 @@ in {
# options = "--delete-older-than 30d"; # options = "--delete-older-than 30d";
# }; # };
# to free up to 100GiB whenever there is less than 1GiB left # to free up to 10GiB whenever there is less than 1GiB left
extraOptions = '' extraOptions = ''
min-free = ${toString (1024 * 1024 * 1024 * 1)} min-free = ${toString (1024 * 1024 * 1024)}
max-free = ${toString (1024 * 1024 * 1024 * 100)} max-free = ${toString (1024 * 1024 * 1024 * 10)}
''; '';
}; };
@ -71,40 +75,32 @@ in {
settings.PermitRootLogin = "prohibit-password"; settings.PermitRootLogin = "prohibit-password";
}; };
users = { users.users.root = {
mutableUsers = false; initialHashedPassword = "";
users.root = { openssh.authorizedKeys.keys = [
hashedPasswordFile = config.age.secrets.root_pw.path; # no obligation to have name attached to keys
openssh.authorizedKeys.keys = [ # Root account
# no obligation to have name attached to keys "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK6DjXTAxesXpQ65l659iAjzEb6VpRaWKSg4AXxifPw9 Skynet Admin"
# Root account # CI/CD key
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK6DjXTAxesXpQ65l659iAjzEb6VpRaWKSg4AXxifPw9 Skynet Admin" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBDvexq/JjsMqL0G5P38klzoOkHs3IRyXYO1luEJuB5R colmena_key"
# CI/CD key # Brendan Golden
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBDvexq/JjsMqL0G5P38klzoOkHs3IRyXYO1luEJuB5R colmena_key" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEHNLroAjCVR9Tx382cqdxPZ5KY32r/yoQH1mgsYNqpm Silver_Laptop_WSL_Deb"
# Brendan Golden "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKjaKI97NY7bki07kxAvo95196NXCaMvI1Dx7dMW05Q1 thenobrainer"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEHNLroAjCVR9Tx382cqdxPZ5KY32r/yoQH1mgsYNqpm Silver_Laptop_WSL_Deb" ];
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKjaKI97NY7bki07kxAvo95196NXCaMvI1Dx7dMW05Q1 thenobrainer"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDxHpsApRyCvuP2ToGm46G308Og8lO7BYPuz+EqHVU5w esy root"
];
};
}; };
# skynet-admin-linux will always be added, individual servers can override the groups option # skynet-admin-linux will always be added, individual servers can override the groups option
services.skynet.ldap_client.enable = true; services.skynet_ldap_client.enable = true;
networking = { networking = {
# every sever needs to be accessable over ssh for admin use at least # every sever needs to be accessable over ssh for admin use at least
firewall.allowedTCPPorts = [22]; firewall.allowedTCPPorts = [22];
resolvconf.useLocalResolver = false;
resolvconf.extraConfig = "name_servers='193.1.99.120 193.1.99.109'";
# explisitly stating this is good # explisitly stating this is good
defaultGateway = { defaultGateway = {
address = "193.1.99.65"; address = "193.1.99.65";
@ -130,21 +126,19 @@ in {
# https://discourse.nixos.org/t/systemd-networkd-wait-online-934764-timeout-occurred-while-waiting-for-network-connectivity/33656/9 # https://discourse.nixos.org/t/systemd-networkd-wait-online-934764-timeout-occurred-while-waiting-for-network-connectivity/33656/9
systemd.network.wait-online.enable = false; systemd.network.wait-online.enable = false;
environment.systemPackages = with pkgs; [ environment.systemPackages = [
# for flakes # for flakes
git pkgs.git
git-lfs
# useful tools # useful tools
ncdu_2 pkgs.ncdu_2
htop pkgs.htop
nano pkgs.nano
nmap pkgs.nmap
bind pkgs.bind
zip pkgs.zip
traceroute pkgs.traceroute
openldap pkgs.openldap
screen pkgs.screen
inetutils
]; ];
}; };
} }

View file

@ -1,56 +0,0 @@
/*
Name: Link to where information on the name can be found
Why: Why is it named this
Type: VM/Physical
Hardware: - if its a VM, the hardware (PowerEdge r210) if its physical
From: 2023/2024/2025/...
Role: What role does it have in teh cluster
Notes:
*/
{
pkgs,
lib,
nodes,
...
}: let
# name of the server, sets teh hostname and record for it
name = "name";
# Assigned IP address
ip_pub = "193.1.99.000";
# dont need to change these
hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
};
in {
# what configurrations to import, email in this example
imports = [
../applications/email.nix
];
deployment = {
# dont need to change these
targetHost = hostname;
targetPort = 22;
targetUser = null;
# deployment option: active-dns/active-core/active-ext/active
tags = [
"active"
];
};
services.skynet = {
# pass in the details of the host server
host = host;
# enable the backup service
backup.enable = true;
# enable the imported service
email.enable = true;
};
}

View file

@ -17,12 +17,6 @@ Notes: Used to have Agent Smith as a partner but it died (Ironically)
name = "agentjones"; name = "agentjones";
ip_pub = "193.1.99.72"; ip_pub = "193.1.99.72";
hostname = "${name}.skynet.ie"; hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
interface = "eno1";
};
in { in {
imports = [ imports = [
./hardware/RM001.nix ./hardware/RM001.nix
@ -37,14 +31,43 @@ in {
tags = ["active-firewall"]; tags = ["active-firewall"];
}; };
services.skynet = { skynet_dns.records = [
host = host; {
backup.enable = true; record = name;
r_type = "A";
value = ip_pub;
server = true;
}
{
record = ip_pub;
r_type = "PTR";
value = hostname;
}
];
services.skynet_backup = {
host = {
ip = ip_pub;
name = name;
};
}; };
# keep the wired usb connection alive (front panel) # keep the wired usb connection alive (front panel)
# networking.interfaces.enp0s29u1u5u2.useDHCP = true; # networking.interfaces.enp0s29u1u5u2.useDHCP = true;
networking.hostName = name;
# this has to be defined for any physical servers
# vms are defined by teh vm host
networking = {
defaultGateway.interface = lib.mkForce "eno1";
interfaces.eno1.ipv4.addresses = [
{
address = ip_pub;
prefixLength = 26;
}
];
};
# this server is teh firewall # this server is teh firewall
skynet_firewall = { skynet_firewall = {
# always good to know oneself # always good to know oneself

View file

@ -1,49 +0,0 @@
/*
Name: https://en.wikipedia.org/wiki/Eagle_Eye
Why: ARIIA - Autonomous Reconnaissance Intelligence Integration Analyst
Type: VM
Hardware: -
From: 2024
Role: Metrics gathering and Analysis
Notes:
*/
{
config,
pkgs,
lib,
nodes,
...
}: let
# name of the server, sets teh hostname and record for it
name = "ariia";
ip_pub = "193.1.99.83";
hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
};
in {
imports = [
../applications/grafana.nix
];
deployment = {
targetHost = hostname;
targetPort = 22;
targetUser = null;
tags = [
# "active-core"
];
};
services.skynet = {
host = host;
backup.enable = true;
prometheus.server.enable = true;
grafana.enable = true;
};
}

View file

@ -1,51 +0,0 @@
/*
Name: https://en.wikipedia.org/wiki/Bumblebee_(Transformers)
Why: Created to sell toys so this vm is for games
Type: VM
Hardware: -
From: 2024
Role: Game host
Notes:
*/
{
pkgs,
lib,
nodes,
arion,
...
}: let
# name of the server, sets teh hostname and record for it
name = "bumblebee";
ip_pub = "193.1.99.91";
hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
};
in {
imports = [
../applications/pelican/pelican.nix
../applications/games/minecraft.nix
];
deployment = {
targetHost = hostname;
targetPort = 22;
targetUser = null;
tags = ["active"];
};
services.skynet = {
host = host;
backup.enable = true;
pelican = {
wing = {
enable = true;
node_name = "node01";
};
};
};
}

View file

@ -18,11 +18,6 @@ Notes:
name = "cadie"; name = "cadie";
ip_pub = "193.1.99.77"; ip_pub = "193.1.99.77";
hostname = "${name}.skynet.ie"; hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
};
in { in {
imports = [ imports = [
../applications/nextcloud.nix ../applications/nextcloud.nix
@ -36,10 +31,33 @@ in {
tags = ["active"]; tags = ["active"];
}; };
services.skynet = { skynet_dns.records = [
host = host; {
backup.enable = true; record = name;
nextcloud.enable = true; r_type = "A";
value = ip_pub;
server = true;
}
{
record = ip_pub;
r_type = "PTR";
value = hostname;
}
];
services.skynet_backup = {
host = {
ip = ip_pub;
name = name;
};
};
services.skynet_nextcloud = {
enable = true;
host = {
ip = ip_pub;
name = name;
};
}; };
# this was causing a conflict for some reason # this was causing a conflict for some reason

View file

@ -1,49 +0,0 @@
/*
Name: https://futurama.fandom.com/wiki/Calculon
Why: Public Service server
Type: VM
Hardware: -
From: 2024
Role: Public services such as Nix Cache, Open governance stuff.
Notes:
*/
{
pkgs,
lib,
nodes,
inputs,
...
}: let
name = "calculon";
ip_pub = "193.1.99.82";
hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
};
in {
imports = [
../applications/nix_cache/nix_cache.nix
../applications/open_governance/open_governance.nix
../applications/open_governance/keyserver.nix
];
deployment = {
targetHost = hostname;
targetPort = 22;
targetUser = null;
tags = ["active"];
};
services.skynet = {
host = host;
backup.enable = true;
nix-cache.enable = true;
open-governance.enable = true;
keyserver.enable = true;
};
}

View file

@ -18,29 +18,45 @@ Notes:
name = "earth"; name = "earth";
ip_pub = "193.1.99.79"; ip_pub = "193.1.99.79";
hostname = "${name}.skynet.ie"; hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
};
in { in {
imports = [ imports = [
../applications/skynet.ie/skynet.ie.nix ../applications/skynet.ie.nix
../applications/skynet.ie/wiki.nix
]; ];
deployment = { deployment = {
targetHost = hostname; targetHost = ip_pub;
targetPort = 22; targetPort = 22;
targetUser = null; targetUser = null;
tags = ["active-core"]; tags = ["active-core"];
}; };
# it has two network devices so two
skynet_dns.records = [
{
record = name;
r_type = "A";
value = ip_pub;
server = true;
}
{
record = ip_pub;
r_type = "PTR";
value = hostname;
}
];
services.skynet_backup = {
host = {
ip = ip_pub;
name = name;
};
};
services.skynet = { services.skynet = {
host = host; host = {
backup.enable = true; ip = ip_pub;
website.enable = true; name = name;
wiki.enable = true; };
}; };
} }

View file

@ -19,11 +19,6 @@ Notes:
name = "galatea"; name = "galatea";
ip_pub = "193.1.99.111"; ip_pub = "193.1.99.111";
hostname = "${name}.skynet.ie"; hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
};
in { in {
imports = [ imports = [
../applications/ulfm.nix ../applications/ulfm.nix
@ -37,9 +32,32 @@ in {
tags = ["active"]; tags = ["active"];
}; };
services.skynet = { skynet_dns.records = [
host = host; {
backup.enable = true; record = name;
ulfm.enable = true; r_type = "A";
value = ip_pub;
server = true;
}
{
record = ip_pub;
r_type = "PTR";
value = hostname;
}
];
services.skynet_backup = {
host = {
ip = ip_pub;
name = name;
};
};
services.skynet_ulfm = {
enable = true;
host = {
ip = ip_pub;
name = name;
};
}; };
} }

View file

@ -18,11 +18,7 @@ Notes:
name = "gir"; name = "gir";
ip_pub = "193.1.99.76"; ip_pub = "193.1.99.76";
hostname = "${name}.skynet.ie"; hostname = "${name}.skynet.ie";
host = { #hostname = ip_pub;
ip = ip_pub;
name = name;
hostname = hostname;
};
in { in {
imports = [ imports = [
../applications/email.nix ../applications/email.nix
@ -36,9 +32,35 @@ in {
tags = ["active-core"]; tags = ["active-core"];
}; };
services.skynet = { # add this server to dns
host = host; skynet_dns.records = [
backup.enable = true; {
email.enable = true; record = name;
r_type = "A";
value = ip_pub;
server = true;
}
{
record = ip_pub;
r_type = "PTR";
value = hostname;
}
];
services.skynet_backup = {
host = {
ip = ip_pub;
name = name;
};
};
# we use this to pass in teh relevent infomation to the
services.skynet_email = {
enable = true;
host = {
ip = ip_pub;
name = name;
};
domain = "skynet.ie";
}; };
} }

View file

@ -19,15 +19,9 @@ Notes: Each user has roughly 20gb os storage
name = "glados"; name = "glados";
ip_pub = "193.1.99.75"; ip_pub = "193.1.99.75";
hostname = "${name}.skynet.ie"; hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
};
in { in {
imports = [ imports = [
../applications/git/forgejo.nix ../applications/gitlab.nix
../applications/git/forgejo_runner.nix
]; ];
deployment = { deployment = {
@ -35,16 +29,35 @@ in {
targetPort = 22; targetPort = 22;
targetUser = null; targetUser = null;
tags = ["active-git"]; tags = ["active-gitlab"];
}; };
services.skynet = { skynet_dns.records = [
host = host; {
backup.enable = true; record = name;
forgejo.enable = true; r_type = "A";
forgejo_runner = { value = ip_pub;
enable = true; server = true;
secret = ../secrets/forgejo/runners/token2.age; }
{
record = ip_pub;
r_type = "PTR";
value = hostname;
}
];
services.skynet_backup = {
host = {
ip = ip_pub;
name = name;
};
};
services.skynet_gitlab = {
enable = true;
host = {
ip = ip_pub;
name = name;
}; };
}; };
} }

View file

@ -9,7 +9,6 @@ Role: LDAP Server
Notes: Notes:
*/ */
{ {
config,
pkgs, pkgs,
lib, lib,
nodes, nodes,
@ -19,20 +18,13 @@ Notes:
name = "kitt"; name = "kitt";
ip_pub = "193.1.99.74"; ip_pub = "193.1.99.74";
hostname = "${name}.skynet.ie"; hostname = "${name}.skynet.ie";
host = { #hostname = ip_pub;
ip = ip_pub;
name = name;
hostname = hostname;
};
in { in {
imports = [ imports = [
../applications/ldap/server.nix ../applications/ldap/server.nix
../applications/ldap/backend.nix
../applications/discord.nix ../applications/discord.nix
../applications/discord_t-800.nix
../applications/bitwarden/vaultwarden.nix ../applications/bitwarden/vaultwarden.nix
../applications/bitwarden/bitwarden_sync.nix ../applications/bitwarden/bitwarden_sync.nix
../applications/sso.nix
]; ];
deployment = { deployment = {
@ -43,23 +35,46 @@ in {
tags = ["active-core"]; tags = ["active-core"];
}; };
services.skynet = { # add this server to dns
host = host; skynet_dns.records = [
backup.enable = true; {
record = name;
r_type = "A";
value = ip_pub;
server = true;
}
{
record = ip_pub;
r_type = "PTR";
value = hostname;
}
];
# ldap setup services.skynet_backup = {
ldap.enable = true; host = {
ldap_backend.enable = true; ip = ip_pub;
name = name;
};
};
# private member services services.skynet_ldap = {
discord_bot.enable = true; enable = true;
host = {
ip = ip_pub;
name = name;
};
};
# for logging on our own discord services.discord_bot = {
discord_bot_t-800.enable = true; enable = true;
};
# committee/admin services services.skynet_vaultwarden = {
vaultwarden.enable = true; enable = true;
sso.enable = true; host = {
ip = ip_pub;
name = name;
};
}; };
} }

View file

@ -17,11 +17,6 @@ Notes:
name = "marvin"; name = "marvin";
ip_pub = "193.1.99.81"; ip_pub = "193.1.99.81";
hostname = "${name}.skynet.ie"; hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
};
groups = [ groups = [
"skynet-admins-linux" "skynet-admins-linux"
@ -49,13 +44,31 @@ in {
++ groups_trusted; ++ groups_trusted;
# allow trainees access # allow trainees access
services.skynet.ldap_client = { services.skynet_ldap_client = {
groups = groups; groups = groups;
sudo_groups = groups; sudo_groups = groups;
}; };
services.skynet = { skynet_dns.records = [
host = host; {
backup.enable = true; record = name;
r_type = "A";
value = ip_pub;
server = true;
}
{
record = ip_pub;
r_type = "PTR";
value = hostname;
}
];
services.skynet_backup = {
host = {
ip = ip_pub;
name = name;
};
}; };
# Put test services below this
} }

View file

@ -18,17 +18,24 @@ Notes:
name = "neuromancer"; name = "neuromancer";
ip_pub = "193.1.99.80"; ip_pub = "193.1.99.80";
hostname = "${name}.skynet.ie"; hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
interface = "eno1";
};
in { in {
imports = [ imports = [
./hardware/RM007.nix ./hardware/RM007.nix
]; ];
networking.hostName = name;
# this has to be defined for any physical servers
# vms are defined by teh vm host
networking = {
defaultGateway.interface = lib.mkForce "eno1";
interfaces.eno1.ipv4.addresses = [
{
address = ip_pub;
prefixLength = 26;
}
];
};
deployment = { deployment = {
targetHost = hostname; targetHost = hostname;
targetPort = 22; targetPort = 22;
@ -37,8 +44,25 @@ in {
tags = ["active-core"]; tags = ["active-core"];
}; };
services.skynet = { skynet_dns.records = [
host = host; {
backup.server.enable = true; record = name;
r_type = "A";
value = ip_pub;
server = true;
}
{
record = ip_pub;
r_type = "PTR";
value = hostname;
}
];
services.skynet_backup = {
server.enable = true;
host = {
ip = ip_pub;
name = name;
};
}; };
} }

View file

@ -17,16 +17,11 @@ Notes:
}: let }: let
# name of the server, sets teh hostname and record for it # name of the server, sets teh hostname and record for it
name = "optimus"; name = "optimus";
ip_pub = "193.1.99.90"; ip_pub = "193.1.99.112";
hostname = "${name}.skynet.ie"; hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
};
in { in {
imports = [ imports = [
../applications/pelican/pelican.nix ../applications/games.nix
]; ];
deployment = { deployment = {
@ -37,11 +32,32 @@ in {
tags = ["active"]; tags = ["active"];
}; };
services.skynet = { skynet_dns.records = [
host = host; {
backup.enable = true; record = name;
pelican = { r_type = "A";
panel.enable = true; value = ip_pub;
server = true;
}
{
record = ip_pub;
r_type = "PTR";
value = hostname;
}
];
services.skynet_backup = {
host = {
ip = ip_pub;
name = name;
};
};
services.skynet_games = {
enable = true;
host = {
ip = ip_pub;
name = name;
}; };
}; };
} }

View file

@ -22,6 +22,9 @@ Notes: Thius vpn is for admin use only, to give access to all the servers via
hostname = ip_pub; hostname = ip_pub;
in { in {
imports = [ imports = [
# applications for this particular server
../applications/firewall.nix
../applications/dns.nix
]; ];
deployment = { deployment = {
@ -36,7 +39,7 @@ in {
"ip daddr ${ip_pub} udp dport 51820 counter packets 0 bytes 0 accept" "ip daddr ${ip_pub} udp dport 51820 counter packets 0 bytes 0 accept"
]; ];
services.skynet.dns.records = { skynet_dns.records = {
external = [ external = [
"${name} A ${ip_pub}" "${name} A ${ip_pub}"
]; ];

View file

@ -18,21 +18,16 @@ Notes: Does not host offical sites
name = "skynet"; name = "skynet";
# DMZ that ITD provided # DMZ that ITD provided
ip_pub = "193.1.96.165"; ip_pub = "193.1.96.165";
# for internal network connectivity
ip_int = "193.1.99.82";
hostname = "${name}.skynet.ie"; hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
interface = "eth1";
cidr = 28;
};
in { in {
imports = [ imports = [
../applications/skynet_users.nix ../applications/skynet_users.nix
]; ];
deployment = { deployment = {
targetHost = hostname; targetHost = ip_pub;
targetPort = 22; targetPort = 22;
targetUser = null; targetUser = null;
@ -40,9 +35,29 @@ in {
tags = ["active-ext"]; tags = ["active-ext"];
}; };
services.skynet = { skynet_dns.records = [
host = host; {
backup.enable = true; record = name;
website_users.enable = true; r_type = "A";
value = ip_pub;
server = true;
}
{
record = ip_pub;
r_type = "PTR";
value = hostname;
}
];
services.skynet_backup.host = {
ip = ip_pub;
name = name;
};
services.skynet_users = {
host = {
ip = ip_pub;
name = name;
};
}; };
} }

View file

@ -18,18 +18,13 @@ Notes: Using the server that used to be called Earth
name = "vendetta"; name = "vendetta";
ip_pub = "193.1.99.120"; ip_pub = "193.1.99.120";
hostname = "${name}.skynet.ie"; hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
# only required for physical servers
interface = "eno1";
};
in { in {
imports = [ imports = [
./hardware/RM002.nix ./hardware/RM002.nix
]; ];
networking.hostName = name;
deployment = { deployment = {
targetHost = ip_pub; targetHost = ip_pub;
targetPort = 22; targetPort = 22;
@ -38,16 +33,47 @@ in {
tags = ["active-dns" "dns"]; tags = ["active-dns" "dns"];
}; };
services.skynet = { networking = {
host = host; # needs to have an address statically assigned
backup.enable = true;
dns = { defaultGateway.interface = lib.mkForce "eno1";
server = { interfaces.eno1.ipv4.addresses = [
enable = true; {
# primary dns server (ns1) address = "193.1.99.120";
primary = true; prefixLength = 26;
ip = ip_pub; }
}; ];
};
services.skynet_backup = {
host = {
ip = ip_pub;
name = name;
}; };
}; };
skynet_dns = {
server = {
enable = true;
# primary dns server (ns1)
primary = true;
ip = ip_pub;
};
records = [
# vendetta IN A 193.1.99.120
{
record = name;
r_type = "A";
value = ip_pub;
server = true;
}
# 120 IN PTR vendetta.skynet.ie.
{
record = ip_pub;
r_type = "PTR";
value = hostname;
}
];
};
} }

View file

@ -17,11 +17,6 @@ Notes:
name = "vigil"; name = "vigil";
ip_pub = "193.1.99.109"; ip_pub = "193.1.99.109";
hostname = "${name}.skynet.ie"; hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
};
in { in {
imports = [ imports = [
]; ];
@ -34,16 +29,36 @@ in {
tags = ["active-dns" "dns"]; tags = ["active-dns" "dns"];
}; };
services.skynet = { services.skynet_backup = {
host = host; host = {
backup.enable = true; ip = ip_pub;
dns = { name = name;
server = {
enable = true;
# secondary dns server (ns2)
primary = false;
ip = ip_pub;
};
}; };
}; };
skynet_dns = {
server = {
enable = true;
# secondary dns server (ns2)
primary = false;
ip = ip_pub;
};
# this server will have to have dns records
records = [
# vigil IN A 193.1.99.109
{
record = name;
r_type = "A";
value = ip_pub;
server = true;
}
# 109 IN PTR vigil.skynet.ie.
{
record = ip_pub;
r_type = "PTR";
value = hostname;
}
];
};
} }

View file

@ -18,14 +18,9 @@ Notes:
name = "wheatly"; name = "wheatly";
ip_pub = "193.1.99.78"; ip_pub = "193.1.99.78";
hostname = "${name}.skynet.ie"; hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
};
in { in {
imports = [ imports = [
../applications/git/forgejo_runner.nix ../applications/gitlab_runner.nix
]; ];
deployment = { deployment = {
@ -33,15 +28,32 @@ in {
targetPort = 22; targetPort = 22;
targetUser = null; targetUser = null;
tags = ["active-git"]; tags = ["active-gitlab"];
}; };
services.skynet = { skynet_dns.records = [
host = host; {
backup.enable = true; record = name;
forgejo_runner = { r_type = "A";
enable = true; value = ip_pub;
secret = ../secrets/forgejo/runners/token1.age; server = true;
}
{
record = ip_pub;
r_type = "PTR";
value = hostname;
}
];
services.skynet_backup = {
host = {
ip = ip_pub;
name = name;
}; };
}; };
services.skynet_gitlab_runner = {
enable = true;
runner.name = "runner01";
};
} }

View file

Binary file not shown.

View file

@ -1,21 +1,17 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 V1pwNA kWC0Tr0nlHEelEzS9xAzZ5UwI1vTgeaBS+zQJCxHe1A -> ssh-ed25519 V1pwNA LoF1ddALOVnrPikVoFfIO/Hrydrqoh/4W5DaSMZHkUs
dcVKgK28SA4abje/xfC2bqlDzrkThJh0hpsyCtfGPDM Fla3oxohjlE6oUkx9tsroXcbDqQoQfi4qixrEqy2+/4
-> ssh-ed25519 4PzZog H/hrMeDv4EmuSvR79vX7spZyF6t506ZKVHWHl4HN1wQ -> ssh-ed25519 4PzZog tojPturHggZ54bUlyCbr0hwLbhTPpBR/o90XT9DYf0Y
E4+skv4K1fTqG1cIbRqRr89Ti6D78wxEzap3Sl0UZU8 it+mlc2OKzxnEF08ao0J+aJezA20eAaRBW+ODgiX09k
-> ssh-ed25519 dA0vRg SgmoRqftGwIG34Py02bfdEv2HlI6fPBiKmcBmz2VaiI -> ssh-ed25519 5Nd93w W5FDJ7geDB27elGpL6SHBA54Al3uTU67FNsTt63E5H4
DKzlODXbQf9xzUzJHlwtIZbGw3qG2ApfssEF1/nZe+Q 1N3NVwEC3QqjpwdFk/SRWFpTUk1tTH7YPQdV2MmF/II
-> ssh-ed25519 5Nd93w Q8fxVcYwxbeXJzpKCOWH4/D3t8bWSUm9E4spASzIKnQ -> ssh-ed25519 q8eJgg yJj2ImpyTpjLGiPqxQ/03tGFDnDN08Gr93rPRUYLLyk
80fe2FiI+5OTojxu32OfFJwS3l/cMPr+5tErOr5wmcM PLSFba8JFM2na4h6XIzVeKKEw61/ZwlpQdesIHPtggY
-> ssh-ed25519 q8eJgg zgw/JH1HOdTE38Cr/61gcGo6OruuFUCAUJ4wmNHSXWs -> ssh-ed25519 3pl/Kw Zu5dWL1GkgL8ZhmFuTg56GRGTvTTDXYOXGN75/h37wQ
l7ta9JGOwCZCjnfui2Zo3PVF+Ge/UoPL0xm5lZ0GGF8 nvNXCSa/VsjchPWRMoFNCRLe6SK/trUrGgKa7iJkprA
-> ssh-ed25519 KVr8rw CcJymhaWM76X91C0ECPlZqaN2IARwxo1WMZRmlevnzA -> vZ[z@fHA-grease
syAw8YySWxtDonZ5txKVNynCdziInCzy4u5kv6mH8PU mAV/h887fY2ispnlxuTZ+LR/EIYhV6LqbyuDpEc4p0jnwdpYhEAfU4KKZtnxae22
-> ssh-ed25519 fia1eQ 0ocrOjhQ+CEJK8Li3rDegYkMXkBpjAAStjgvVHGQx3Q q/IM3g
YORVM3sEbE6PLVuwfMkxe9gYqTVVT7DGoG+kQcxaPiQ --- QXUMgsJS6LdbF4du60HslLfcBq5xNsazlzAHb7jSeDI
-> ssh-ed25519 Km71ZA 9W2stpyr/9osFppfqBDjeDzZ6ltU+spmBoeWJ+I8sys |á©eC Ÿ® ¶>,ÎVÄ•Ë<E280A2>3Mb<4D>$iœ¥IŽsÒ=qk܃œDi
C6DGgwvbwW0r1E3L6o7LUOnPo/n8Sl8tGzm3NlsXGcw ÖŸîè;S¸´)ßÄ<+€ÔÆìò)¨uRê²—[ÍðŒ4©}¢{61Wr ÈEíëPI
-> ssh-ed25519 3pl/Kw pm1noozCEdPbd4f8rkSD/gicvfWTEN1kvYp7TLb68Uo
VH2XUbhIf4nYTmp6rkGt99RcI2xxa7F9QXmDp88r1CY
--- lNlQ5pwix455easITfJ8dztlPYg8Pi77sbAsOQF19dI
#@3öá|ÈKíÛ%ké±xL,ò5°x/QTbz<04> ÆjÀ.”7ÿÏÇ-]2ñbùí_ ><16>éNëJamÀ¬^ë„á CðŒÒ]VvhÔ|<7C>ý¡¢DÌ€"

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,21 +1,15 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 V1pwNA UWCmhr1Mj4BVH+0MJ2zBCRQMVYFK+eEp2AhdYTWSRiw -> ssh-ed25519 V1pwNA BxPb6d6nlJHiTkbcwOoPrvAPBuR1iJSFAXIp9n23Ix0
EL7DlSXyemeZtJw+1SO+vSf2NGg/sPEz5r+p3OntrFo hl0X3RjOEYp2G1QU4SC6CBF5YVlCWiakMsRbGTBYkzs
-> ssh-ed25519 4PzZog HIqzyRkhsIgOgxBNZK1HBTBUIpHPDZEhIfo9zmXEqzU -> ssh-ed25519 4PzZog Nf/tUysmhTfzaoHhubwdQ5NKZw5SBd3CEs129FGkuio
2m9H93js26tJJHwM4ce+8DH7oLf3zEBeQ3sT3zHpOP0 750oaBtfeBEpDuasZFr7RY5uBzFZZNMNGQkRyFfEGCo
-> ssh-ed25519 dA0vRg 1W13Q5mX61EH31BM/FEk7l92Lo/5WuoMLo39wmwVjW4 -> ssh-ed25519 5Nd93w fI9TNLWkDkvLCDA8eTMfVw7fRPylWHPGzPupya737xY
raNdTsgJcKlwqmBE+zVEjfL6VPyzHhcMpNrcl6Y6DmY wQcz+yf+EqDNmRWqldNuQjjy9tKc1zN//yumtGpGbaM
-> ssh-ed25519 5Nd93w 2gYsG5vFoosuvJo+O+eQscfyoLqYBxOReiT5kdV+bBE -> ssh-ed25519 q8eJgg T9Iv+fRwmOLYMXe3ur6dqudA1z2wQsKQX6ogkyQT3Fw
82ghrnctaXECGxn77VT6YfGPuDKwfh+dJ/+3/SBTA8Y LBYKL2OtLiwq25FkvZjT4H3tu8fOA+KFmFp5vjbncLI
-> ssh-ed25519 q8eJgg vzSwKw4EzJksqujeJqfg+1YNM3sgp5Zw7Qld+XNS21Y -> ssh-ed25519 IzAMqA O9JfKAlOUao2S14iczlnTzT2sTSAM1vOR5KjO8eJMG0
65wJiSlqdjZm3Ps2Dg4DB0LzPLgwcYQvJgRvRkeblBw ioTSe6X4E6jE4c9Utl2d6EUHZYilnbtRnB5QJg3S3Q4
-> ssh-ed25519 KVr8rw f2MjAAqmuw4UcgvjkRku9XX+SYqY6oAfgS1ayVDVa3Y -> 6&-grease
m1nl/CW9GYaCyShT28JZdECirBJdfBoiK3V2tRBrj5o BkWorA2LiphyWLmdV3AeKsI
-> ssh-ed25519 fia1eQ Zkvg9fYBubmg81c7NqEp9fRbSLm2WKVDil+DwnfuPlw --- +MO1wX7pJf7eq4MkiWSP+xyxThI5jnfseS8jd7LbFoY
NN+1CMVxAstqBT7qqAhL9whaEvyWgsNXgBOSWmjTqtA ¿ÕWV¥—>ådD­"ð`ûi+ €Ç¸ÃæÕ¬ã<C2AC>ÂSмk°H¨Ojt<6A>±Ç*âòkßäŒØ<C592>ŒÔ¢9Ë×P
-> ssh-ed25519 Km71ZA kfU2W/uwQORahVWcg1qYQ5Q2QhZnAkbzjv9As4fJfis
w+rVDQ0oyLGqTT8yVr7mCOV+55dItAcALIa4ABw5bDI
-> ssh-ed25519 IzAMqA Ir8ygCowpY6f4egB9xqplPzP4mJFL1sh+JaQVZrtZEk
y679U8nCE9L8seAvVypssgj2p7aZlIW2Q2TgQqHhpoU
--- Dh0JCQdTvVZYtwnzgqEl+WHxOTXmOzr4/TaHz45r+fc
ý.¼0ôzY­'”oaï.Èe-ßê%ñÕ5?(Ê|€ŽàuÌsýº;ÞìŒ*/Ë©Éw²Ð£0Vp

View file

@ -1,26 +1,22 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 V1pwNA 6NKUbOSUbwVjzW/ZUpl8qEiUTTegFlji4+tVJyqY3SE -> ssh-ed25519 V1pwNA icye7bxeLugaCuSwMYAZQOrI7tcG8uc9XR5lTYBkWQ4
fRQvaKnLMkVBboTEriQpWlGY9VBAP3ppsEbAB2QTScs HRsRB0GVkMPS0afDz0ybcTZ/oexA7zV9U6hYyyVm/hQ
-> ssh-ed25519 4PzZog mp/+b5LpB+DvRduqAZiKWqkZq6+tlyQgVTZz7Oge2Us -> ssh-ed25519 4PzZog ihJwwtlgiICUNgrpwVVKAAcDP9JxPgBmcruW1em8RU4
OycqmZyDr3levWSfRFxypJOkITLDix0Q15Todya6BNc /c6JJDzrHwyEelgMaoDeADVD/yL+ptrDdgSSMFceuXs
-> ssh-ed25519 dA0vRg yp/4LvS9DbdatHFWFsP5qhH8CP8Bs0IjVSenUtG4+Xs -> ssh-ed25519 5Nd93w aLRd09zpjgCnj84pFFfPd9FrJGsnemOb99EG/TPe+UM
hHiJEtl1ffYXltsJzuEMLGUl2i/i3pFzv4bjbx/cbOI hEM/T5j4oZI05597dI148eRbRU0P/E02RAD5ypsl1eo
-> ssh-ed25519 5Nd93w BTngmy4NGLGKhC8lPos63QEVBKoQT82KswQ22EypcQQ -> ssh-ed25519 q8eJgg dwCo6ph1KTMDgFnJLrGFtzscrHxog6WGRUaPdBOuCSo
OCnJMkOwwXQVbtCitUizXM4nynC6a1tiPSkm7MxulWA WCxgbOjZy9vkgcYTa4t/bgc5qfxlpFOiQ3vtCvb+uWM
-> ssh-ed25519 q8eJgg NaEjVcDBVICRgXuJchEdE4vg3qmkNmJAbDDxLq1fX0M -> ssh-ed25519 IzAMqA Q+XUnmVUAstlxgZTiXXGZN7Nzo6G0zgS3jtil8MKd0w
YFwUmEPwJIik5YJ2SV5IAmqGlY+h24voJJlrBaoCBwA 1VFkeEGLZLh+j7e1RJW1iCx8ueLNTljTsxpujkhwBPI
-> ssh-ed25519 KVr8rw ZnyVITZFkuozEs/rbTdxXDQNS3Nggo+JkBL1Icht2SM -> ssh-ed25519 uZzB3g FeuGUR8zcPUHkev9PVARM2ac4Ezk9EjO3gWL15kkjjM
B4jVVts5lK1kIlOWMl0eiN7TpsTeJZWIu7NqildxeGE W7DXwMWrIKEzs2IJ4MH/diaqkUK+lYE5ocJ3qD26NyU
-> ssh-ed25519 fia1eQ kvzARRScl/eypC2a5cY66sXcH+TZqz4sYg4W/k9iJxQ -> ssh-ed25519 Hb0ipQ +hueeoIxI4+E0bkElclszUoD4ftHLkiqe6XGcMNbAn4
Ga+4TVvXiQ6i5/+fgUQ3E5tJiLqdBsEsXjenXEpRV/A mS/SFhLfjQYa76qhDXvMijkvbWkGRGcv7HWlszArX14
-> ssh-ed25519 IzAMqA 5sizvlhLhAhAR1bViHJtRJ8fAIO56TAuLVSOwE177QE -> ssh-ed25519 IzAMqA CLf1vDYSLjW2InHfHCEfq/b7j3zyRH0TTcLSQ0Evmn4
b9oJ8BC2xiBjvc3D0H0EF7bSNDlpvIidyBCTf04ndJI tuq2+h0UVzt/lTFdpLn+fr5rIYdf8mgdDny8Cak+k3c
-> ssh-ed25519 uZzB3g g9y66zNmQbqP6Rbhg2t06W3YOgy8DkRvJZbWVegT71s -> x-grease
2dH7E76tDMrWQJbLPefyORP66iaPHQnSjwu8NCdSyJo Eeo9UQ7LVOjORlpR2Jf7K6P2OEdc6HWWQ6/Yt//KHWxKStUtMv2fPIHu3A8h8mHl
-> ssh-ed25519 Hb0ipQ azOzBLXfshInlFVpV0PzIBidL/VzA/+kKRXFFVD6ZF4 iQT/Xmlg
iXBF/Wcv4KWo5qUXUlyimuo0l6aClKxOCtkm3MxAIBc --- 0/OGiJqIu2aFUO8vqJ936PvDDNiohDSVkqpsiCxzfiE
-> ssh-ed25519 IzAMqA EWitYyV8RsPIB6HEFE2OI/C1zcC6WfBEeDI62rGVmkk —Z ¥lŽ.§j¥õßZöE‡¤ääóÓ´ì€Fx®6Mœ!ã:øö‘×û¼ÁzbªùÎ.tDΊz#:xãc}<r0n£°/èþ*?·ÿÓ*;Ûò؈kzùûîAõÑO"†”|K>?cF£/ÑÅÎØ‰Õ;Ë<>¤"´eJM_Gv·©e7ôck»\E9<45>³à&öOúž+â< ÁÚ“+ýÕŠ 2«Hm<48>½
Bk9tdSqIjLjat21J2LM8RXAt9GwdQxYdfPzqDtCjunE
--- waY7j+HMEOdqEZs/TcLEhUY9gJs6ZSc51VNfuCmCxJ4
Ý;dÙ9A‡vÔé±nq<“ê;TèáƒB؇$ÐGÌvï¯h
»\^Žé§lÖ¯`š¼ÄÎ?l¸ <0C>au~üЧ×yâ[ךju²ü;]!œ6Ëè±ãXIs4ÇŒ!Ù@ß϶û¬‘|›úïª">eÈÿ[Vž´,ÿ5˜ý8N§¹Œh<04><>[ƒ×´ZD,&âñíó¡”õIØ>ŠØù¡<C3B9>|ÎézÉm

Binary file not shown.

View file

@ -1,21 +1,17 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 V1pwNA ZmQJhSsBijnPyy9g8sevoYI18vapGSd7vJEk5i6oQFg -> ssh-ed25519 V1pwNA 93P7isaXS0ubudR6/CvDIRo4UYTwpUM12ZgWsE3EQD4
3PiR70vhl9bNEasbKS95eAslG6FXTzf5zv3bvup7lGk GrCYzZ9y5WeBH9stCigfWyWWLCrc2BUfdj8jUdOGcK4
-> ssh-ed25519 4PzZog owlHOHv+kwFw5d39zBs5sIUgNCuvzfLd4dlSYmEbxH4 -> ssh-ed25519 4PzZog T9HjJq6TUcB4+L2jg/x26YSRSq6eIr0jkLKgV6pdrF8
AgRbOyxjZQJqOF48buY5HGLl40Od/EcoLgRWy0wWUmk O+ZP0KMq6TwayInqpn1lqcE5qYniBalLvd/KT+DJm1k
-> ssh-ed25519 dA0vRg BFa20JXsy8A5oSp4uVPx4A1et+R16QEUVO2pu+88BzA -> ssh-ed25519 5Nd93w F7Y23jPUIN+tYxYFe7kBmKSAi6tnLCzIDZ9y/mIrGyQ
+MyPvk3j3fSWZCQugjqViMX0NC/6UTytC9u0sEZlGv8 wf8Ba7hIKcMyayWNkE2hGbmcFjzBJhIPfSgddTZGKX4
-> ssh-ed25519 5Nd93w QKJg+FXCJocbH8KYqYv55Jdd594jlrmkUfiEDS7KnQ0 -> ssh-ed25519 q8eJgg nRknjq1O8SLveHb6ealr7+adyIpQjCh337EZe5YGvjc
9ztGS6I4oQxIXTCWIMzeuKDq1WFdsiPzU+SXfDCWNFw uEwiABnhwtkZyCkg51m8j4bab29hucc9osjdEUn94yw
-> ssh-ed25519 q8eJgg eR+Qq87fdU7bBN5+z30+v8xCMW6HZWfUn7XPSq93jjU -> ssh-ed25519 IzAMqA cDP/4uytlvVCXCWXX2gA1f141XOpvN6SedVeYI3ilAA
uw8cFeKOnL65VmVwH380onmHmGXQ7g8VNNBBFYq5Z0I yAqhLzZ8P2DOK3t/0Ci4wxuu3QYOXv1SuqiJQcrBS6c
-> ssh-ed25519 KVr8rw 6e1x7tMiDSQSiHMOqce6XtarIUxB8IJH4BOP0Gre5Ds -> z>=+-grease n
eDmu2kLyeCu99FFGVOUsNhc6wfTGpdYRM2eAd6wChgE HkWYFtqUkB+F6ILYc1DigRV7P9l2066/gzkYwStY5Q+d
-> ssh-ed25519 fia1eQ ObshdBHUyxu2nOUjiCwZzdHgQ+ZPUxQpntn9vTDDt2o --- P0PdlJkFtzCZBnFAXMs6yzv2jVHYVx572IIglfNzf+U
RofPfltKZbwl47iNazej45Y6BdMy2OcHxMgx/SW79zg cxÍÇŤMŁŽćâq,hż°€:m­ôVŃÎjĎJµř皏+L%#ř
-> ssh-ed25519 Km71ZA iGUcuJS2p6W6HEAdMxtyTcBzjK2Cn36IV69Vyix1aVA z ĂŻJ·cioÇ…˙9…ĽâdĽű¶T©'¨[.€<>ŞJ?¸Š96Ů}Î<>6×ď·öŇÎ+˘®ó Žě=ÚIč.Z]("Ĺ‹ŚV$;^ ><3E>Ŕ,öb±µ!çĐË<C490>gŁ>mťŔ
9t1c7CALGHKIl32bU/Kcnnia3IBX1UUxNNRKCqHOnQw ĐeW¬U=VĐăçßUÚŕJ»¬ŰqţzËw
-> ssh-ed25519 IzAMqA tL7x2ArzpKQfJUazHt7/dyXo3m7i/0j5cirw1ZKfNTQ
IPWqmXZvEQBh0EfUZGfA2pKaCjrZH1ZRGfXW9udEJu0
--- S2eIVWpdL+G2AzQbu82N23DP9Mey4DV6Zu9DuBdEZ60
QWËe<r<>[{ON@β&™ÎôîS=€Y¾ ¥­_rÁ„j¬~ÆÃÃÿÙ5K<35>ªÕ#iÏ»Æ0F 5¸8÷ÕØA¨{e´Í--^¦p<C2A6>üäñ”<E2809D>Ø>u3™°Ë|Á<>åüJÝdüÔ}±Ž1\ý—ããÚ“Ô“F)$çÜx.tØ4]د¢ðTò®-^^"I±ú¿é¦^´dÊdI@Þ¯@ù]°6¢3< fÀŽ%Sß8výL†P¦— u]ñž§Ò,4L;gƒVÄ„ÿ¯¦â©¦<C2A9>"utè–ä®%ˆÆáƒO2øöUµzËÎ{L ŒíY<E280BA><E280A1>¥©µï|

Binary file not shown.

Binary file not shown.

View file

@ -1,29 +1,22 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 V1pwNA sW9NG3ZnVZ7XN4iMceA+WNwEmGp5mB8fYRML4JMxTx4 -> ssh-ed25519 V1pwNA /YhGxaH+uVC4EXVNEpY6akQ3cyOFTCvbqnQDobPGbHE
Ugwsmg4yXfq9YH99RoV2MymOyhHn+WEFbhSq3jOS+Jk pcRmdrS2h6GOmhiUQmbDncgAhfBMsI7pVc/8MrCQeiM
-> ssh-ed25519 4PzZog ncbPVDYkLeBV89U+YKVSGRyNDIdLDuN/YV9AiGcYfkY -> ssh-ed25519 4PzZog dsRhlBiY7h+WrKqU7KlCYQ5Ypwz76uH9AjZlfLwf/3M
rifseFii9IZI6t2cDfhi1GXQQRngI8IM+3H8znbMA/0 wNvcPHNISI5y0eGQpAv2jSZbTbA9C8LGzI8/dnMn3ZY
-> ssh-ed25519 dA0vRg ZU44BDl8VU2ri+qNYEEj8GF4x4gGUQPnr6YlFA5itGk -> ssh-ed25519 5Nd93w 5z8u2rWibJcfnkKJmtIv/toSUgkJdxk2HiBJ5yi1F34
zV29wfmrtyxEU1JFEm5P7pfkWwzmNpXflfLRsyZ3vCA jXWyd2UcJgQLKHyl8/SbtR5uKEBPS1TWcSV+uQ6sudQ
-> ssh-ed25519 5Nd93w BCqKxqNscTU2iEm4h/78KCzMjRWtHlO3rwZZjq2lJFQ -> ssh-ed25519 q8eJgg puPp2e3TvJOmqF68x25NsZftZOjXoQRAfT3d6dulOwE
Y9yLQ33RvcO1g3a1q3w47Y0kgg1NZpdlYk34LrZ69mw DMKRvgnqQKJbUcKlFvFPnIWQF48v/AhR0sRG7R01LMg
-> ssh-ed25519 q8eJgg lWbDTedbgvxvGpMPDWdrghAKO3duh85kaOR+7xsPd3E -> ssh-ed25519 IzAMqA bkxqFYf3QFk4Bg+ax6l2B2/qEC1Sc2v1oNIXRxA942E
MzwcVM+gzJ/IApGVZNNM+RuYp7EKZyxCDjRkipL3aYU TYk7gMneWdKdx9PMJoROZy6k0A9smhQGoenypCiSSjE
-> ssh-ed25519 KVr8rw 8vJTA9ABfwuZyFwhFZD4n187b6gmq7zCLALqp56mFyw -> ssh-ed25519 uZzB3g ouKif0gJlk8Ijg4htLxS6V9kDm1oO10pgoIDGHlnKg0
iQ4MtJ1YtYycFi8qCs4N0/nIXccaw2swi9yIvOLmVmA TtChPqbY4BWc6320hBVsdjOYsN8FZ7+kK+gAa8cPrXU
-> ssh-ed25519 fia1eQ hZzB90WDGom3oaOlWlcBg8iAMAfbZGyosgFIa8AiTWI -> ssh-ed25519 Hb0ipQ GQu3BHKFNOffCTgN6v/9dciTpSDOPHSD9L1R6OG74Hw
HekDEc26Y121KRtKLavDD1xKcaClVgn2tGPrgQYWQBo j9r+idSNJR0w6XgVZCGOdVsvsFPVbyc1/Nno4uqBCUw
-> ssh-ed25519 Km71ZA uunwnxdg7A6ZGTbV51r5XL/2hJN/VFIUas0TVxid0Xc -> ssh-ed25519 IzAMqA cQNK62FYAGQY9+0YhVvVuKMaqB9IBPLUPCnM2nSUQzI
zGx6iHfu+rZ9WbtIITtzDk0nzkFCeIRQpdRVoj7dj0E NOMoBDtIN9w1WlxuYHTLORS2xA//D8jIip4SidBUNog
-> ssh-ed25519 IzAMqA 17lTeNgkOhX6iOPix/YeKZyztDHYLu6OIjZOctANpmQ -> QjVPV-grease z #u>.AWX
fu8VIba1ZNy3QvnVk3bPmCA1n6/dcB02epAs0GLb6zE ZAgcrfjgpw5J778jd9fRtQUns32SsiEybe/VTFKZw7P4J9STzRlt8/KDn8EJQ2Dh
-> ssh-ed25519 uZzB3g I0QOJAnUor5hnoKDlFeSuW82o94zcWcs6VvKTq37lVo K22xl+ENBo/+YuN1UQ
S6o+cem4L12E8V/DzbvL75azwrhLgZJXkxWXuCd4+Z4 --- TYTyl621sRrBSPvYgf8uC3auUXL2ytoFi0ob6+NUSOw
-> ssh-ed25519 Hb0ipQ cEsppH2jMi71R0513L/vq7MaFYYWiRrWZKricdhW/H8 Žpns1 èž”{ ìjÏ7iˆ™'™WÓÍWôÈ<C388> ðË¿ú©²?+Óê/P\ú~B}æ<Ú…ƒwIü.Wâ;ÚórF‡Ä‡d³HgÎ>™åþõ?Õ½ŒÙÜTl"ïÞ-1_äñõKz¾ÁómEÕÜ™¼×A”Y{d0,VÕñ8YV 
IvRQejJ2AOQAeWUumh4an0LUSBJYMMnOIr9PU8FjYiA
-> ssh-ed25519 IzAMqA cL7V3gfdSkpHtkcDhaH0ATTWUzBir09Xhe91wlaGJ14
GU8IQvHlwyBBONJKufQRwEr7nZy6y36XszV+E97VA94
--- Nq7IuDZY4GM8UBq0wdEnn/kZEJRdUlmqR75SlX75Q7w
oÖT·¹ëjˆo¬çÅ(Rð«Z¹lðmÑ’&f7;a8¦÷B£€ò|±ûù«Ó”B/l ”ª
îÉÐg#˜Lò†‰"‹Ù/* ¶,aÜ…ã€.f.QÄ
Õ“¨oEÃM×V=å2ä¦q÷;IawkFØ\" Ÿç±Q¾7$.`MûR§XúÛ°

Binary file not shown.

View file

@ -1,23 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 V1pwNA ZZzPHXiieqnKeatxqOpOyJJdPCSrpU151rNY3PgewCc
usq82uQE6qxnwb5EYHlfXSl1A+oqV/DZcKlHmheNrLs
-> ssh-ed25519 4PzZog GPaAefwdrHHdkDJT4OHYFdmjUbXEQz3lLkGfu2M/c30
hoWO80LE9PEMkqlQLD4WXIDc9rgX0uMbNzHkiXcVWRM
-> ssh-ed25519 dA0vRg 1WCuZ91cuKBZi7gFFVArvvAvMh6aU0AufX2vDHiXvTI
yUUbM5kXyyiNlvV7UWXNNhBe3JZ+ZxdoXf1FRwQiHt4
-> ssh-ed25519 5Nd93w 8HkcjdSrVbg3TQFn/ldlqYEU3aPHFBIcXnzovwMv2Vc
+2kX+X1uYoUnyUyLYLLWeRw99OC3St30ky6Xsf7ls+Y
-> ssh-ed25519 q8eJgg moUF6G0Qsz6+vJTMFoKIusiCfapHvaRBdOoB9r2uP00
limKEFL+4G28+jc5pOiNt1OkpQRzSXKq+3If8/Dfe+E
-> ssh-ed25519 KVr8rw /G4TpEFysiCx/eF25IA9gjmX4w1yGM6m2Lx1mTmf0mU
nXIuYPbV3S+0+3Ce45iPeAzZlIr1i0RnGWSLg3KBH5I
-> ssh-ed25519 fia1eQ tXV4gH4gIjFYWNxLV0AQVOvahTtvFWK5W6tNZTjA9ig
pxpIIZ4+/ItpG6nolOS7lxGwSkhwq1XvdxePxWsJYCE
-> ssh-ed25519 Km71ZA QRM3tBeZJGVMwZ51ZBlxGIzwGOyMB9ppGNq4pUyRsHo
+0QO4JlKaOUH5MY+w02Rq0DDNk76eSD2EVIAvQeiZ9Y
-> ssh-ed25519 CqOTGQ Ystm+4YnAlTTYPiHBXVa8lM/MGEfZ3OcmxiT8QcdKSY
F2b5grk6m2sVnhhWF68WxUemgtZHYSIJZ9e7eBKtIjA
-> ssh-ed25519 uZzB3g PepFlWAg+221m5eOVoNl1TIRVrS6lpkrQ9Dgce+Grwc
6/8sTiO+P/HgNbB8YyRVylAPPp3lwF4D6FbWWaPSxtE
--- 0PQ3rJZdbEfye9mLMrQJ0jGvJSiZ+9dh9Bv6bpGEBNs
^;­Yh=p«3<C2AB>>FÂ:2b6û+¥C²À“ÅEÉ6Ÿ3óýT´EÚ.è[,'¼È3„¢<E2809E>¯P 6_|ê *AÇùÓQ*ôj¬cƒ

View file

@ -1,23 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 V1pwNA Lw89KnIDDurZQ0UaqDS1utTrKCGXR+Uxs3od/5n09io
1JECYcXRBNWwzoagvEKeoWoW2d8da15eWPfTD8nKqX0
-> ssh-ed25519 4PzZog LB5CnkEPX2RH8vWdD15KMs/qgNbw3e7G8qCV1CMf8kE
pO77W91WR/8MRPLIuJrLk5ib9CPp7xHuUmTS8fmQ3KM
-> ssh-ed25519 dA0vRg QhtuGTY1MEpEjRahnU3WtON6Xda7y3HvGXpB3HcDfBk
6sCAQhU4K2nQ5pMbGYY75TKUXxZ4BKHCb6sOHMAuNEA
-> ssh-ed25519 5Nd93w 2QcbhnmxOkTrRUMrHR4X3spMUnsLXN9DDnh49qFAYx0
SD47vo7tOPWmvXR2wTj+BSsxJUqnlXOu8HlTEOExeC4
-> ssh-ed25519 q8eJgg 9TqmbSDG4KOl14FNZmZKFZ5Q/60K657phquz+qpIgyU
odOvsccHqgXoC7WgKcFjJDm5it9ZGm5ifjU2pt5hQZ4
-> ssh-ed25519 KVr8rw w0fZq3VUrN8wi4UrhMUfrviUiaWl4Ol+tbTXN/urISs
TY+dO2Z6TmN9DBPuo1vyxgeXbDcqZlRoP+Q1IN6O/ks
-> ssh-ed25519 fia1eQ 5Aqk1jkUQkomeBioV7LAPMzurJ1dHdYHbzLHXH7mrRQ
j+7aPUOeJAI10FL4DjXKlYEkC25gM7TNy/X5vFk68+8
-> ssh-ed25519 Km71ZA S9le6/bZxnkPVuCLqiYc8VMk8LXlk0BVJUtJYc/CmB4
DTjvS3wBo+RHy0klprrgKS1wYAMAkfzPkpw/ip7KwpE
-> ssh-ed25519 CqOTGQ xba3GuenbljaFEcgaX5UknPWjJSyQOMBaJSGk4VHZg4
uzGnhgquJHT4+0zop9wNg6Fm8ka/9Ri1yPjw65VnGtA
-> ssh-ed25519 uZzB3g WaU+50ui82IQHobA1QB62WX7bnjgxSVy9LAGjYifuHI
H0O4GIRchLil79zqim5v46RT8Xbu5zi0dKSRPiT6kHc
--- vg0SOy4LbcYEcxJMe6lbREFPPcxrRI/dJM7Lx3VC1rQ
bx‰â¯mVâ^hŽ0•Þúl@ƒôôŸRy€ñS\rÈéÐÕµ;œ@™±t~U«YM)œÃAø?Ʋ<C386>W˹m,1I“

Binary file not shown.

View file

@ -1,22 +1,16 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 V1pwNA dHoon26BhGIqe6TjYS7Q93OC2vhr64B7ofHzX8FiJxk -> ssh-ed25519 V1pwNA 82JAj5XsvsKT8sIuARe4FTmSiCygEhTive+jIJ7h/R8
EcH7j44+zOHBcJOw0AwpziXtUPxOH//MGacSa7rDNT0 M3U8He0axy2HLdKnmKDyvilT99LQPEkw27FF2hUI3tI
-> ssh-ed25519 4PzZog CrrMq81Ep/Gm9qYcZjRJ1IpXtFGp/1XDfBCB6OSGbiY -> ssh-ed25519 4PzZog c45jK9DTUO6sXTbhs8UrUjLIELIL8XVdYiOYZsR/4yY
gJ+PFL0Sx7izMk54jJr3LPvfZ9DMQP5/FjAXkRw/mkc HS4ng3Sb4J0f9OYHZLmWHWS/c3uetn3w6HG80uZNdUY
-> ssh-ed25519 dA0vRg r5S3Fqlmqeeeu75r9COpp4mS07YWY0HP11zby9AjCyY -> ssh-ed25519 5Nd93w fBv3U1fx4kIQcPWAMl1xRUeIwiM1+0FpfhJZrHQMww4
DGkeIp0M6dIA4WM4KYVZiwalHjou6qzLOFUnksIPU2Q 8ANUGKVp5Tpq/wbIgXhpi5cPsxFALOuOsisMEN5A4j0
-> ssh-ed25519 5Nd93w bm2DM8tuydnEqbcM7/aMgHtU/cnnfENGHgMgXPft414 -> ssh-ed25519 q8eJgg HTr8SCqna6YrbpdEWdXf3vcR/ohxQStlXabHjZN+zW8
7bFV4Mx/gSaEM7+rJbqjjuod0U7tl8ODbK1+qY7gtmE vyoLfNsO0zW+S2+nIHfB1s8GaD/XjfqnPq/i3G4IJqs
-> ssh-ed25519 q8eJgg 35Ce/4wweXHadDG1ryl1d53G7IxEOwOFQATYgC6WzBY -> ssh-ed25519 uZzB3g f6+fXpF/3aP36u+G1sDOhaQtdaWXwxoW2aWWC5E8X0Y
5va0fHjZXbH/2ZAFioTcmyeFCid8vrgTFXK6wR/ranA KRDi36ChFupksZMkxWEnUkaNBgZujYsXEhS7ngueo8E
-> ssh-ed25519 KVr8rw dyfXPAGfWlbmjpiol87idweWsU/c1v4gwq18Y/4oZBo -> /Q|[]_7-grease WOAZ6f R~_\$m7
MiuhfBeQeMlHsi7hz0OgOiLIbFjeSaUoJ+xlIHkAmpY e0+qF+9VouiUjHXF8coBkESl7COpdlPlBQYamcTsTto6CgZUZkYqWQ
-> ssh-ed25519 fia1eQ +GTfP3+0hcdmM9qtZvUw2bZ+32guClfXwRTfvOg5Tzc --- n0CQNPMTO1iiR+zt+dDvj0FocVteXkclIlI0EXoKV7w
8gSAdoh1DRoiD6KTpm5F/hFvT02/3bf4ayD/dICjpTs OÐâr€é¥ÜP¼K]PK<>ðxò>ÿe3rðd™¹Éçž¿¢½÷ôÝÆÀŸݦ9d¾Ñ4¿G cά<C38E>|T7gÕ7ßz
-> ssh-ed25519 Km71ZA g3doqjZJ0GP9PgkZ5l/ePPxI3gyvILvrQAx4En6r2kA P”¤º´ôó02ïïÀb¶Ú<C2B6>„fäÇ,ÔÒ¨<C392>Ñâ2Åm  ‰ŽÌz^»]M$jùƒñÒi7uYŒØ_lNPuÌA%·<ô@Ž« €c„²ÿõ{7
O2lJGGq/LLsjtzwnfyUSD8Avw+5KbuNGd5XA8FwWJOw
-> ssh-ed25519 uZzB3g 79FGgQhIwzLPTKUBhv6RdT3RqBe+JRb3DYLPt5mAPDg
gp9dUDfNPnhAX75SJhFxBmyNdaH8umAQcYzjBHkPEoo
--- XZ+0tCvAK9SgY5daynCjTqE5M0N3ip+wVIg8o/18AEs
`ÁT6,NH]ÝÄåÒ‘ÿ*q»zíC«'‰€T
#\ÔL‡b0zðB•«Æ F̽H@ À†·ùs! "zêÁÖ«ë8Çj} Õí%ÐFEiÌ ä…ŽB¬fü@†A˜­JµÚq¨}cÀUC=Ä%s¢&lbpË€\<Ühx1K&ñ<>¥3Li˜¦¬|—Çý(_°Ô2©ËXg

Some files were not shown because too many files have changed in this diff Show more