Compare commits

..

No commits in common. "main" and "add_automx2" have entirely different histories.

123 changed files with 2492 additions and 7365 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 }}"

6
.gitattributes vendored
View file

@ -1,9 +1,3 @@
# Git config here
* text eol=lf
#############################################
# Git lfs stuff
# Documents
*.pdf filter=lfs diff=lfs merge=lfs -text
*.doc filter=lfs diff=lfs merge=lfs -text

9
.gitignore vendored
View file

@ -4,10 +4,6 @@
# Microsoft office Lockfiles
~$*
*.tmp
tmp
# open office tmp lockfiles
.~lock.*
# Test files
test.*
@ -26,8 +22,3 @@ test.*
# Dealing with Mac users
.DS_Store
# nixos stuff
result
/result
.gcroots

View file

@ -1,23 +1,21 @@
# borrowed from https://gitlab.com/nix17/nixos-config/-/blob/main/.gitlab-ci.yml
stages:
- misc
- flake
- test
- deploy
- deploy_gitlab
#- deploy
# Update the flake for any changes upstream
# Passed in from upstream
# $PACKAGE_NAME = name of the flake that needs to be updated
# $UPDATE_FLAKE = flag to update the flake
update:
stage: misc
tags:
- nix
stage: flake
# from https://forum.gitlab.com/t/git-push-from-inside-a-gitlab-runner/30554/5
before_script:
# set teh ssh key for the commit
- eval $(ssh-agent -s)
#- 'which ssh-agent || ( apt-get update -qy && apt-get install openssh-client -qqy )'
- eval `ssh-agent -s`
# for the deploy
- echo "${CI_KEY}" | tr -d '\r' | ssh-add - > /dev/null
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
@ -30,142 +28,50 @@ update:
# the part that updates the flake
- nix --experimental-features 'nix-command flakes' flake lock --update-input $PACKAGE_NAME
- 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
- 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/compsoc/skynet/nixos.git
- git push origin HEAD:$CI_COMMIT_REF_NAME
only:
refs:
- main
variables:
- $UPDATE_FLAKE == "yes"
sync_repos:
stage: misc
image: registry.gitlab.com/gitlab-ci-utils/curl-jq:2.0.0
script:
- cd sync
- chmod +x ./sync.sh
- ./sync.sh
rules:
- if: $UPDATE_FLAKE == "yes"
when: never
- if: '$CI_PROJECT_NAMESPACE == "compsoc1/skynet" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
changes:
- sync/repos.csv
.scripts_base: &scripts_base
# load nix environment
- . "$HOME/.nix-profile/etc/profile.d/nix.sh"
- nix --extra-experimental-features 'nix-command flakes' profile install nixpkgs#colmena
.scripts_deploy: &scripts_deploy
# setup ssh key
- eval $(ssh-agent -s)
- echo "$DEPLOY_KEY" | tr -d '\r' | ssh-add - > /dev/null
- mkdir -p ~/.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
.build_template: &builder
tags:
- nix
before_script:
- *scripts_base
- *scripts_cache
rules:
- if: $UPDATE_FLAKE == "yes"
when: never
- changes:
- applications/**/*
- machines/**/*
- secrets/**/*
- flake.*
- .gitlab-ci.yml
- config/**/*
# deploy items only run on main
.deploy_template: &deployment
before_script:
- *scripts_deploy
- *scripts_base
- *scripts_cache
rules:
- if: $UPDATE_FLAKE == "yes"
when: never
- if: '$CI_PROJECT_NAMESPACE == "compsoc1/skynet" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
changes:
- flake.nix
- flake.lock
- applications/**/*
- machines/**/*
- secrets/**/*
- config/**/*
linter:
<<: *builder
stage: test
script:
- nix --extra-experimental-features 'nix-command flakes' fmt -- --check .
build:
<<: *builder
# image: nixos/nix
stage: test
before_script:
- . "$HOME/.nix-profile/etc/profile.d/nix.sh"
script:
- nix --extra-experimental-features 'nix-command flakes' develop
- colmena build -v --on @active-dns
- colmena build -v --on @active-core
- colmena build -v --on @active
- colmena build -v --on @active-ext
- colmena build -v --on @active-git
- nix --experimental-features 'nix-command flakes' run nixpkgs#colmena -- build
# dns always has to be deployed first
deploy_dns:
<<: *builder
<<: *deployment
stage: deploy
script:
- colmena apply -v --on @active-dns
# use ctrl+/ on intellij to mass uncoment
# set up deployment later
#deploy:
# stage: deploy
# # from https://forum.gitlab.com/t/git-push-from-inside-a-gitlab-runner/30554/5
# before_script:
# # Check for ssh-agent + rsync and install if not present
# #- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
# - eval $(ssh-agent -s)
# # Inject the remote's private key
# - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null
# - mkdir -p ~/.ssh
# - chmod 700 ~/.ssh
# # Append keyscan output into known hosts
# - ssh-keyscan $SERVER_IP >> ~/.ssh/known_hosts
# - chmod 644 ~/.ssh/known_hosts
#
# script:
# # this will grab a fresh copy of teh repo
# - ssh $SERVER_USER@$SERVER_IP "cd /etc/nixos && git stash && git pull origin main && nixos-rebuild switch"
#
# only:
# refs:
# - main
deploy_core:
<<: *builder
<<: *deployment
stage: deploy
needs:
- deploy_dns
script:
- colmena apply -v --on @active-core
# only run on $UPDATE_FLAKE
deploy_active:
<<: *builder
<<: *deployment
stage: deploy
needs:
- deploy_dns
script:
- colmena apply -v --on @active
# this is just skynet server
deploy_ext:
<<: *builder
<<: *deployment
stage: deploy
needs:
- deploy_dns
script:
- colmena apply -v --on @active-ext
deploy_gitlab:
<<: *builder
<<: *deployment
stage: deploy_gitlab
script:
- colmena apply -v --on @active-git
when: manual

View file

@ -1,18 +0,0 @@
## Ticket ID
## Ticket URL
## Ticket HTML
1. Expand all sections of ticket
2. Right click on page
3. Save page as
4. Web page complete
5. Attach file here
## Important
* Mark as ``Confidential``
* Apply label ``ITD Ticket``
* After submission link any relevent issues.

View file

@ -1 +0,0 @@
Brendan Golden <silver@skynet.ie> <git_laptop@brendan.ie> <git@brendan.ie>

View file

@ -1,45 +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'
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'

View file

@ -1,24 +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,Active,193.1.99.090,Debian-12,Games server manager (replacing SKYNET00006 soon)
SKYNET00017,bumblebee,Active,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,Active,193.1.99.085,Nixos,Testing flake for Pelecian
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 Active 193.1.99.090 Debian-12 Games server manager (replacing SKYNET00006 soon)
18 SKYNET00017 bumblebee Active 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 Active 193.1.99.085 Nixos Testing flake for Pelecian

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

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,20 +0,0 @@
https://web.archive.org/web/20180815150202/https://wiki.skynet.ie/Admin/SkynetMachines
https://en.m.wikipedia.org/wiki/Category:Fictional_artificial_intelligences
https://en.wikipedia.org/wiki/List_of_artificial_intelligence_films
* agentsmith
* skynet
* caro
* Lowe - https://westworld.fandom.com/wiki/Bernard_Lowe
* ultron
* walle
* eve
* calculon
* deepthought
* earth
* flexo
* bender
* marvin
* kitt
* wopr
* wintermute

125
README.md
View file

@ -1,125 +0,0 @@
# Skynet
This is teh core config for teh skynet cluster which uses [NixOS][1].
## Dev
### Prep
1. Install [Nix][2]
2. Enable [Flakes][3]
The system ye use does nto matter much, I (@silver) use nix in wsl and it works grand.
### Shell
Now ye got nix installed and flakes enabled run ``nix develop`` in the root folder (same place this readme is).
The dev dependencies you need to work with the project will be automatically installed.
The specific config for this can be found [here][4].
Specifically it installs [Colmena][5] and [Agenix][6].
Colmena is a build and deployment tool, Agenix is for secret management.
All following commands are inside the shell.
### Colmena
#### Building
To build all nodes (servers) run:
```shell
colmena build
```
To build a specific one
```shell
colmena build --on skynet
```
To build a group (for example the dns servers)
```shell
colmena build --on @active-dns
```
#### Deploy
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.
One such case is the ``@active-git`` group if either Gitlab or Gitlab-runner got updated.
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``
```ini
Host *.skynet.ie 193.1.99.* 193.1.96.165
User username
IdentityFile ~/.ssh/skynet/username
IdentitiesOnly yes
```
Then you can run the following commands like so:
```shell
colmena apply
colmena apply --on @active-dns
colmena apply --on @active-git
```
The CI/CD pipeline has a manual job that can be triggered to update ``@active-git`` if you know it wont cause issues.
### Agenix
Agenix is for storing secrets in an encrypted manner using ssh keys.
All these commands require you to be in the secrets folder ``cd secrets``
#### Prep
1. Go to yer .ssh folder and see if you have a ``id_ed25519`` key ([tutorial][7])
2. Make a pull request to add (``id_ed25519.pub``) to the [secrets config][8].
3. An existing admin will pull, run ``agenix --rekey`` and commit changes.
4. Once committed and pushed up and merged in, you will be able to edit secrets.
``id_ed25519`` is preferred due to its neatness and security (Yes @silver is pedantic.)
#### Editing
When editing a terminal editor will open (nano).
You must use teh path defined in the ``secrets.nix`` file.
````shell
agenix -e stream_ulfm.age
agenix -e ldap/self_service.age
agenix -e gitlab/runners/runner01.age
````
### Updating inputs
Occasionally you will want to update the inputs for the project.
It is best to do this every few months or so, there is always a risk of things changing so a small pain often is better than a nightmare if left longer.
As seen in [this merge request][9] the layout of one config changed which had to be fixed.
We should be updating ``nixpkgs`` at least once a semester, ideally to teh next NixOS release so we cna show ITD our servers are patched and up to date.
```shell
nix flake lock --update-input nixpkgs
# newser versions
nix flake update nixpkgs
```
### Formatting
Formatting helps keep everything nice and consistent.
The pipeline will only run if the file is correctly formatted.
```shell
nix fmt
```
[1]: https://nixos.org/explore
[2]: https://nixos.org/download
[3]: https://nixos.wiki/wiki/Flakes
[4]: https://gitlab.skynet.ie/compsoc1/skynet/nixos/-/blob/main/flake.nix#L33
[5]: https://github.com/zhaofengli/colmena
[6]: https://github.com/ryantm/agenix
[7]: https://docs.gitlab.com/ee/user/ssh.html#see-if-you-have-an-existing-ssh-key-pair
[8]: https://gitlab.skynet.ie/compsoc1/skynet/nixos/-/blob/main/secrets/secrets.nix#L2
[9]: https://gitlab.skynet.ie/compsoc1/skynet/nixos/-/merge_requests/4

View file

@ -1,74 +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";
};
};
};
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;
}
];
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,69 +0,0 @@
{
config,
pkgs,
lib,
inputs,
...
}:
with lib; let
name = "games";
cfg = config.services.skynet."${name}";
in {
imports = [
./nginx.nix
./games/minecraft.nix
];
options.services.skynet."${name}" = {
enable = mkEnableOption "Skynet Games";
domain = {
tld = mkOption {
type = types.str;
default = "ie";
};
base = mkOption {
type = types.str;
default = "skynet";
};
sub = mkOption {
type = types.str;
default = "games";
};
};
};
config = mkIf cfg.enable {
services.skynet.dns.records = [
# need a base domain
{
record = cfg.domain.sub;
r_type = "CNAME";
value = config.services.skynet.host.name;
}
];
services.skynet.acme.domains = [
"${cfg.domain.sub}.skynet.ie"
];
services.nginx.virtualHosts = {
"${cfg.domain.sub}.skynet.ie" = {
forceSSL = true;
useACMEHost = "skynet";
root = "${inputs.skynet_website_games.defaultPackage.x86_64-linux}";
};
};
# the minecraft servers
services.skynet.games_minecraft = {
enable = true;
domain = {
sub = "minecraft.${cfg.domain.sub}";
};
};
};
}

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

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

View file

@ -1,76 +0,0 @@
{
pkgs,
config,
lib,
...
}: let
user = "bwdc";
in {
imports = [];
options = {};
config = {
age.secrets.bitwarden_sync_id = {
file = ../../secrets/bitwarden/id.age;
owner = user;
group = user;
};
age.secrets.bitwarden_sync_secret = {
file = ../../secrets/bitwarden/secret.age;
owner = user;
group = user;
};
age.secrets.bitwarden_sync_ldap = {
file = ../../secrets/ldap/pw.age;
owner = user;
group = user;
};
services.bitwarden-directory-connector-cli = {
enable = true;
user = user;
domain = "https://pw.skynet.ie";
ldap = {
ssl = false;
startTls = false;
sslAllowUnauthorized = false;
ad = false;
port = 389;
hostname = "account.skynet.ie";
rootPath = "dc=skynet,dc=ie";
username = "cn=admin,dc=skynet,dc=ie";
};
sync = {
removeDisabled = true;
overwriteExisting = false;
largeImport = false;
memberAttribute = "member";
creationDateAttribute = "skCreated";
users = true;
userPath = "ou=users";
userObjectClass = "inetOrgPerson";
userEmailAttribute = "skMail";
userFilter = "(|(memberOf=cn=skynet-committee,ou=groups,dc=skynet,dc=ie)(memberOf=cn=skynet-admins,ou=groups,dc=skynet,dc=ie))";
groups = true;
groupPath = "ou=groups";
groupObjectClass = "groupOfNames";
groupNameAttribute = "cn";
};
secrets = {
ldap = config.age.secrets.bitwarden_sync_ldap.path;
bitwarden = {
client_path_id = config.age.secrets.bitwarden_sync_id.path;
client_path_secret = config.age.secrets.bitwarden_sync_secret.path;
};
};
};
};
}

View file

@ -1,83 +0,0 @@
{
config,
pkgs,
lib,
inputs,
...
}:
with lib; let
name = "vaultwarden";
cfg = config.services.skynet."${name}";
domain_sub = "pw";
domain = "${domain_sub}.skynet.ie";
in {
imports = [
];
options.services.skynet."${name}" = {
enable = mkEnableOption "Skynet VaultWarden server";
};
config = mkIf cfg.enable {
#backups = [ "/etc/silver_ul_ical/database.db" ];
# Website config
services.skynet.acme.domains = [
domain
];
services.skynet.dns.records = [
{
record = domain_sub;
r_type = "CNAME";
value = config.services.skynet.host.name;
}
];
services.nginx.virtualHosts = {
"${domain}" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/" = {
proxyPass = "http://127.0.0.1:${toString config.services.vaultwarden.config.ROCKET_PORT}";
};
};
};
# has ADMIN_TOKEN and SMTP_PASSWORD
age.secrets.bitwarden_details.file = ../../secrets/bitwarden/details.age;
services.vaultwarden = {
enable = true;
environmentFile = config.age.secrets.bitwarden_details.path;
config = {
DOMAIN = "https://${domain}";
SENDS_ALLOWED = true;
SIGNUPS_ALLOWED = false;
INVITATION_ORG_NAME = "Skyhold";
ORG_GROUPS_ENABLED = true;
USE_SENDMAIL = false;
SMTP_HOST = "mail.skynet.ie";
SMTP_FROM = "vaultwarden@skynet.ie";
SMTP_FROM_NAME = "Skynet Bitwarden server";
SMTP_SECURITY = "starttls";
SMTP_PORT = 587;
SMTP_USERNAME = "vaultwarden@skynet.ie";
SMTP_AUTH_MECHANISM = "Login";
SMTP_EMBED_IMAGES = true;
ROCKET_ADDRESS = "127.0.0.1";
ROCKET_PORT = 8222;
ROCKET_LOG = "critical";
};
};
};
}

View file

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

400
applications/dns.nix Normal file
View file

@ -0,0 +1,400 @@
{ lib, pkgs, config, nodes, ... }:
let
cfg = config.skynet_dns;
# reads that date to a string (will need to be fixed in 2038)
current_date = lib.readFile "${pkgs.runCommand "timestamp" {} "echo -n `date +%s` > $out"}";
# gets a list of records that match this type
filter_records_type = r_type: builtins.filter (x: x.r_type == r_type) records;
filter_records_server = builtins.filter (x: builtins.hasAttr "server" x && x.server) (filter_records_type "A");
filter_records_a = builtins.filter (x: builtins.hasAttr "server" x && !x.server) (filter_records_type "A");
process_ptr = records: lib.lists.forEach records (x: process_ptr_sub x);
process_ptr_sub = record: {record=(builtins.substring 9 3 record.record); r_type="PTR"; value=record.value;};
ip_ptr_to_int = ip: lib.strings.toInt (builtins.substring 9 3 ip);
sort_records_server = builtins.sort (a: b: a.record < b.record) filter_records_server;
sort_records_a = builtins.sort (a: b: (ip_ptr_to_int a.value) < (ip_ptr_to_int b.value)) filter_records_a;
sort_records_cname = builtins.sort (a: b: a.value < b.value) (filter_records_type "CNAME");
sort_records_ptr = builtins.sort (a: b: (lib.strings.toInt a.record) < (lib.strings.toInt b.record)) (process_ptr (filter_records_type "PTR"));
sort_records_srv = builtins.sort (a: b: a.record < b.record) (filter_records_type "SRV");
format_records = records: offset: lib.strings.concatMapStrings (x: "${padString x.record offset} IN ${padString x.r_type 5} ${x.value}\n") records;
# small function to trim it down a tad
padString = text: length: fixedWidthString_post length " " text;
# like lib.strings.fixedWidthString but postfix
fixedWidthString_post = width: filler: str:
let
strw = lib.stringLength str;
reqWidth = width - (lib.stringLength filler);
in
assert lib.assertMsg (strw <= width) "fixedWidthString_post: requested string length (${toString width}) must not be shorter than actual length (${toString strw})";
if strw == width
then str
else (fixedWidthString_post reqWidth filler str) + filler;
# base config for domains we own (skynet.ie, csn.ul.ie, ulcompsoc.ie)
get_config_file = (domain:
''$TTL 60 ; 1 minute
; hostmaster@${domain} is an email address that recieves stuff related to dns
@ IN SOA ${nameserver}.${domain}. hostmaster.${domain}. (
; Serial (YYYYMMDDCC) this has to be updated for each time the record is updated
${current_date}
600 ; Refresh (10 minutes)
300 ; Retry (5 minutes)
604800 ; Expire (1 week)
3600 ; Minimum (1 hour)
)
@ NS ns1.${domain}.
@ NS ns2.${domain}.
; @ stands for teh root domain so teh A record below is where ${domain} points to
;@ A 193.1.99.76
;@ MX 5 ${domain}.
; can have multiple mailserves
@ MX 10 mail.${domain}.
; ------------------------------------------
; Server Names (A Records)
; ------------------------------------------
${format_records sort_records_server 11}
; ------------------------------------------
; A (non server names
; ------------------------------------------
${format_records sort_records_a 18}
; ------------------------------------------
; CNAMES
; ------------------------------------------
${format_records sort_records_cname 31}
; ------------------------------------------
; TXT
; ------------------------------------------
${format_records (filter_records_type "TXT") 29}
; ------------------------------------------
; SRV
; ------------------------------------------
${format_records sort_records_srv 17}
''
);
# https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/4/html/reference_guide/s2-bind-configuration-zone-reverse
# config for our reverse dnspointers (not properly working)
get_config_file_rev = (domain:
''$ORIGIN 99.1.193.in-addr.arpa.
$TTL 60 ; 1 minute
; hostmaster@skynet.ie is an email address that recieves stuff related to dns
@ IN SOA ${nameserver}.skynet.ie. hostmaster.skynet.ie. (
; Serial (YYYYMMDDCC) this has to be updated for each time the record is updated
${current_date}
600 ; Refresh (10 minutes)
300 ; Retry (5 minutes)
604800 ; Expire (1 week)
3600 ; Minimum (1 hour)
)
@ NS ns1.skynet.ie.
@ NS ns2.skynet.ie.
; ------------------------------------------
; PTR
; ------------------------------------------
${format_records sort_records_ptr 3}
''
);
# domains we dont have proper ownship over, only here to ensure the logs dont get cluttered.
get_config_file_old_domains = (domain:
''$TTL 60 ; 1 minute
; hostmaster@skynet.ie is an email address that recieves stuff related to dns
@ IN SOA ${nameserver}.skynet.ie. hostmaster.skynet.ie. (
; Serial (YYYYMMDDCC) this has to be updated for each time the record is updated
${current_date}
600 ; Refresh (10 minutes)
300 ; Retry (5 minutes)
604800 ; Expire (1 week)
3600 ; Minimum (1 hour)
)
@ NS ns1.skynet.ie.
@ NS ns2.skynet.ie.
''
);
# arrys of teh two nameservers
tmp1 = ["193.1.99.109"];
tmp2 = ["193.1.99.120"];
primaries = (if cfg.server.primary then
# primary servers have no primaries (ones they listen to)
[]
else
if builtins.elem cfg.server.ip tmp1 then
tmp2
else
tmp1
);
secondaries = (if cfg.server.primary then
if builtins.elem cfg.server.ip tmp1 then
tmp2
else
tmp1
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
create_cache_networks = (map (x: "193.1.99.${toString x}/32" ) (lib.lists.range 71 126) );
# standard function to create the etc file, pass in the text and domain and it makes it
create_entry_etc_sub = domain: text: {
# Creates /etc/skynet/dns/domain
"skynet/dns/${domain}" = {
user = "named";
group = "named";
# The UNIX file mode bits
mode = "0664";
text = text;
};
};
# (text.owned "csn.ul.ie")
# standard function to create the etc file, pass in the text and domain and it makes it
create_entry_etc = domain: type:
if type == "owned" then
create_entry_etc_sub domain (text.owned domain)
else if type == "reverse" then
create_entry_etc_sub domain (text.reverse domain)
else if type == "old" then
create_entry_etc_sub domain (text.old domain)
else
{};
create_entry_zone = (domain: extraConfig: {
"${domain}" = {
extraConfig = ''
${extraConfig}
// for bumping the config
// ${current_date}
'';
# really wish teh nixos config didnt use master/slave
master = cfg.server.primary;
masters = primaries;
slaves = secondaries;
# need to write this to a file
# using the date in it so it will trigger a restart
file = "/etc/skynet/dns/${domain}";
# no leading whitespace for first line
};
});
text = {
owned = domain: get_config_file domain;
reverse = domain: get_config_file_rev domain;
old = domain: get_config_file_old_domains domain;
};
extraConfig = {
owned =
if cfg.server.primary then
''
allow-update { key rfc2136key.skynet.ie.; };
dnssec-policy default;
inline-signing yes;
''
else
"";
# no extra config for reverse
reverse = "";
old = "";
};
records = builtins.concatLists (
lib.attrsets.mapAttrsToList (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
);
nameserver = if cfg.server.primary then "ns1" else "ns2";
in {
imports = [
../applications/firewall.nix
];
options = {
skynet_dns = {
server = {
enable = lib.mkEnableOption {
default = false;
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
'';
};
};
records = lib.mkOption {
description = "Records, sorted based on therir type";
type = with lib.types; listOf (submodule {
options = {
record = lib.mkOption {
type = str;
};
r_type = lib.mkOption {
type = enum ["A" "CNAME" "TXT" "PTR" "SRV"];
};
value = lib.mkOption {
type = str;
};
server = lib.mkOption {
description = "Core record for a server";
type = bool;
default = false;
};
};
});
};
};
};
config = lib.mkIf cfg.server.enable {
# open the firewall for this
skynet_firewall.forward = [
"ip daddr ${cfg.server.ip} tcp dport 53 counter packets 0 bytes 0 accept"
"ip daddr ${cfg.server.ip} udp dport 53 counter packets 0 bytes 0 accept"
];
services.bind.zones =
(create_entry_zone "csn.ul.ie" extraConfig.owned ) //
(create_entry_zone "skynet.ie" extraConfig.owned ) //
(create_entry_zone "ulcompsoc.ie" extraConfig.owned ) //
(create_entry_zone "99.1.193.in-addr.arpa" extraConfig.reverse )//
(create_entry_zone "conradcollins.net" extraConfig.old )//
(create_entry_zone "edelharty.net" extraConfig.old );
environment.etc =
(create_entry_etc "csn.ul.ie" "owned") //
(create_entry_etc "skynet.ie" "owned") //
(create_entry_etc "ulcompsoc.ie" "owned") //
(create_entry_etc "99.1.193.in-addr.arpa" "reverse") //
(create_entry_etc "conradcollins.net" "old") //
(create_entry_etc "edelharty.net" "old");
# secrets required
age.secrets.dns_dnskeys = {
file = ../secrets/dns_dnskeys.conf.age;
owner = "named";
group = "named";
};
networking.firewall = {
allowedTCPPorts = [53];
allowedUDPPorts = [53];
};
services.bind = {
enable = true;
ipv4Only = true;
# need to take a look at https://nixos.org/manual/nixos/unstable/#module-security-acme-config-dns
extraConfig = ''
include "/run/agenix/dns_dnskeys";
'';
# piles of no valid RRSIG resolving 'com/DS/IN' errors
extraOptions = ''
dnssec-validation yes;
'';
# set the upstream dns servers
# overrides the default dns servers
forwarders = [
# Cloudflare
"1.1.1.1"
# Google
"8.8.8.8"
# Quad9
"9.9.9.9"
];
cacheNetworks = [
# this server itself
"127.0.0.0/24"
# all of skynet can use this as a resolver
/*
Origianl idea, however all external traffic had the ip of the router
"193.1.99.64/26"
So to fix this we need to allow smaller ranges? - Didnt work
Fallback is explisitly listing each ip we have
Now have a function for it
*/
] ++ create_cache_networks;
};
# creates a folder in /etc for the dns to use
users.users.named = {
createHome = true;
home = "/etc/skynet/dns";
};
};
}

View file

@ -1,429 +0,0 @@
{
lib,
pkgs,
config,
nodes,
self,
...
}: let
name = "dns";
cfg = config.services.skynet."${name}";
# reads that date to a string (will need to be fixed in 2038)
current_date = self.lastModified;
# 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
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_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");
# 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_sub = record: {
record = builtins.substring 9 3 record.record;
r_type = "PTR";
value = record.value;
};
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_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_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_srv = records: builtins.sort (a: b: a.record < b.record) (filter_records_type records "SRV");
# a tad overkill but type guarding is useful
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
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;
# like lib.strings.fixedWidthString but postfix
# recursive function to extend a string up to a limit
fixedWidthString_post = width: filler: str: let
strw = lib.stringLength str;
reqWidth = width - (lib.stringLength filler);
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})";
if strw == width
then str
else (fixedWidthString_post reqWidth filler str) + filler;
# base config for domains we own (skynet.ie, csn.ul.ie, ulcompsoc.ie)
# ";" are comments in this file
get_config_file = (
domain: records: ''
$TTL 60 ; 1 minute
; hostmaster@skynet.ie is an email address that recieves stuff related to dns
@ IN SOA ${nameserver}.skynet.ie. hostmaster.skynet.ie. (
; Serial (YYYYMMDDCC) this has to be updated for each time the record is updated
${toString current_date}
600 ; Refresh (10 minutes)
300 ; Retry (5 minutes)
604800 ; Expire (1 week)
3600 ; Minimum (1 hour)
)
; @ stands for teh root domain so teh A record below is where ${domain} points to
@ NS ns1.skynet.ie.
@ NS ns2.skynet.ie.
; ------------------------------------------
; Server Names (A Records)
; ------------------------------------------
${format_records (sort_records_a_server records)}
; ------------------------------------------
; A (non server names
; ------------------------------------------
${format_records (sort_records_a records)}
; ------------------------------------------
; CNAMES
; ------------------------------------------
${format_records (sort_records_cname records)}
; ------------------------------------------
; TXT
; ------------------------------------------
${format_records (filter_records_type records "TXT")}
; ------------------------------------------
; MX
; ------------------------------------------
${format_records (filter_records_type records "MX")}
; ------------------------------------------
; SRV
; ------------------------------------------
${format_records (sort_records_srv records)}
''
);
# 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)
get_config_file_rev = (
domain: ''
$ORIGIN 64-64.99.1.193.in-addr.arpa.
$TTL 60 ; 1 minute
; hostmaster@skynet.ie is an email address that recieves stuff related to dns
@ IN SOA ${nameserver}.skynet.ie. hostmaster.skynet.ie. (
; Serial (YYYYMMDDCC) this has to be updated for each time the record is updated
${toString current_date}
600 ; Refresh (10 minutes)
300 ; Retry (5 minutes)
604800 ; Expire (1 week)
3600 ; Minimum (1 hour)
)
@ NS ns1.skynet.ie.
@ NS ns2.skynet.ie.
; ------------------------------------------
; PTR
; ------------------------------------------
${format_records (sort_records_ptr records)}
''
);
# arrays of teh two nameservers
nameserver_1 = ["193.1.99.109"];
nameserver_2 = ["193.1.99.120"];
primaries = (
if cfg.server.primary
then
# primary servers have no primaries (ones they listen to)
[]
else if builtins.elem cfg.server.ip nameserver_1
then nameserver_2
else nameserver_1
);
secondaries = (
if cfg.server.primary
then
if builtins.elem cfg.server.ip nameserver_1
then nameserver_2
else nameserver_1
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
# now limited explicitly to servers that we are administering
# 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
create_entry_etc_sub = domain: text: {
# Creates /etc/skynet/dns/domain
"skynet/dns/${domain}" = {
user = "named";
group = "named";
# The UNIX file mode bits
mode = "0664";
# content of the file
text = text;
};
};
# standard function to create the etc file, pass in the text and domain and it makes it
create_entry_etc = domain: type: let
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"
then create_entry_etc_sub domain (get_config_file domain domain_records)
# reverse lookups allow for using an IP to find domains pointing to it
else if type == "reverse"
then create_entry_etc_sub domain (get_config_file_rev domain)
else {};
create_entry_zone = domain: let
if_primary_and_owned =
if cfg.server.primary && (lib.lists.any (item: item == domain) domains_owned)
then ''
allow-update { key rfc2136key.skynet.ie.; };
dnssec-policy default;
inline-signing yes;
''
else "";
in {
"${domain}" = {
extraConfig = ''
${if_primary_and_owned}
// for bumping the config
// ${toString current_date}
'';
# really wish teh nixos config didnt use master/slave
master = cfg.server.primary;
masters = primaries;
slaves = secondaries;
# need to write this to a file
# using the date in it so it will trigger a restart
file = "/etc/skynet/dns/${domain}";
# no leading whitespace for first line
};
};
records =
config.skynet.records
/*
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 (
lib.attrsets.mapAttrsToList (
key: value: value.config.services.skynet.dns.records
)
nodes
);
nameserver =
if cfg.server.primary
then "ns1"
else "ns2";
in {
imports = [
../../config/dns.nix
];
options.services.skynet."${name}" = {
server = {
enable = lib.mkEnableOption {
default = false;
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
'';
};
};
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 {
# logging
services.prometheus.exporters.bind = {
enable = true;
openFirewall = true;
};
# services.skynet.backup.normal.backups = ["/etc/skynet/dns"];
# open the firewall for this
skynet_firewall.forward = [
"ip daddr ${cfg.server.ip} tcp 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 = [
{
record = nameserver;
r_type = "A";
value = config.services.skynet.host.ip;
}
];
services.bind.zones = lib.attrsets.mergeAttrsList (
# uses teh domains lsited in teh records
(lib.lists.forEach domains (domain: (create_entry_zone domain)))
# we have to do a reverse dns
++ [
(create_entry_zone "64-64.99.1.193.in-addr.arpa")
]
);
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
age.secrets.dns_dnskeys = {
file = ../../secrets/dns_dnskeys.conf.age;
owner = "named";
group = "named";
};
# basic but ensure teh dns ports are open
networking.firewall = {
allowedTCPPorts = [53];
allowedUDPPorts = [53];
};
services.bind = {
enable = true;
ipv4Only = true;
# need to take a look at https://nixos.org/manual/nixos/unstable/#module-security-acme-config-dns
extraConfig = ''
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
extraOptions = ''
dnssec-validation yes;
'';
# set the upstream dns servers
# overrides the default dns servers
forwarders = [
# Cloudflare
"1.1.1.1"
# Google
"8.8.8.8"
# Quad9
"9.9.9.9"
];
cacheNetworks =
[
# this server itself
"127.0.0.0/24"
# skynet server in the dmz
"193.1.96.165/32"
# all of skynet can use this as a resolver
/*
Origianl idea, however all external traffic had the ip of the router
"193.1.99.64/26"
So to fix this we need to allow smaller ranges? - Didnt work
Fallback is explisitly listing each ip we have
Now have a function for it
*/
]
++ create_cache_networks;
};
systemd.services.bind = {
# deletes teh journal files evey start so it no longer stalls out
preStart = ''
rm -vf /etc/skynet/dns/*.jnl
rm -vf /etc/skynet/dns/*.jbk
'';
restartTriggers = [
"${config.environment.etc."skynet/dns/skynet.ie".source}"
];
};
# creates a folder in /etc for the dns to use
users.groups.named = {};
users.users.named = {
createHome = true;
home = "/etc/skynet/dns";
group = "named";
# X11 is to ensure the directory can be traversed
homeMode = "711";
};
};
}

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

@ -1,151 +1,39 @@
{
config,
pkgs,
lib,
inputs,
...
}:
with lib; let
name = "email";
cfg = config.services.skynet."${name}";
{ config, pkgs, lib, inputs, ...}: with lib;
let
cfg = config.services.skynet_email;
# create teh new strings
create_filter_array = map (x: "(memberOf=cn=${x},ou=groups,${cfg.ldap.base})");
# create teh new strings
create_filter_array = map (x: "(memberOf=cn=${x},ou=groups,${cfg.ldap.base})");
create_filter_join = x: concatStringsSep "" x;
create_filter_join = (x: concatStringsSep "" x);
# thought you could escape racket?
create_filter = groups: create_filter_join (create_filter_array groups);
# thought you could escape racket?
create_filter = (groups: create_filter_join (create_filter_array groups) );
# using +mailbox puts the mail in a seperate folder
create_skynet_email_int = accounts: mailbox: (map (account: "${account}@skynet.ie") accounts);
groups_to_accounts = groups: builtins.concatMap (x: config.skynet.users.${x}) groups;
create_skynet_email_attribute = mailbox: groups: (create_skynet_email_int (groups_to_accounts groups) mailbox) ++ ["int_${mailbox}@skynet.ie"];
create_skynet_email = mailbox: groups: {
name = "${mailbox}@skynet.ie";
value = create_skynet_email_attribute mailbox groups;
};
create_skynet_service_mailboxes = builtins.listToAttrs (map (mailbox: (create_skynet_email mailbox.account mailbox.members)) service_mailboxes);
in {
create_config_to = concatStringsSep "\",\"" (map (mailbox: "${mailbox.account}") service_mailboxes);
service_mailboxes = [
{
account = "root";
members = ["admin"];
}
{
account = "abuse";
members = ["admin"];
}
{
account = "accounts";
members = ["committee"];
}
{
account = "compsoc";
members = ["committee"];
}
{
account = "contact";
members = ["committee"];
}
{
account = "dbadmin";
members = ["admin"];
}
{
account = "dnsadm";
members = ["admin"];
}
{
account = "hostmaster";
members = ["admin"];
}
{
account = "intersocsrep";
members = ["committee"];
}
{
account = "mailman";
members = ["admin"];
}
{
account = "security";
members = ["admin"];
}
{
account = "sysadm";
members = ["admin"];
}
{
account = "webadmin";
members = ["admin"];
}
{
account = "pycon2023";
members = ["committee"];
}
{
account = "skynet_topdesk";
members = ["admin" "trainee"];
}
];
sieveConfigFile =
# https://doc.dovecot.org/configuration_manual/sieve/examples/#plus-addressed-mail-filtering
pkgs.writeText "basic_sieve"
''
require "copy";
require "mailbox";
require "imap4flags";
require ["fileinto", "reject"];
require "variables";
require "regex";
# this should be close to teh last step
if allof (
address :localpart ["To", "Cc"] ["${toString create_config_to}"],
address :domain ["To", "Cc"] "skynet.ie"
){
if address :matches ["To", "Cc"] "*@skynet.ie" {
if header :is "X-Spam" "Yes" {
fileinto :create "''${1}.Junk";
stop;
} else {
fileinto :create "''${1}";
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 {
imports = [
./dns.nix
./acme.nix
./nginx.nix
inputs.simple-nixos-mailserver.nixosModule
# for teh config
../config/users.nix
];
options.services.skynet."${name}" = {
options.services.skynet_email = {
# options that need to be passed in to make this work
enable = mkEnableOption "Skynet Email";
host = {
ip = mkOption {
type = types.str;
};
name = mkOption {
type = types.str;
};
};
domain = mkOption {
type = types.str;
default = "skynet.ie";
@ -175,7 +63,7 @@ in {
hosts = mkOption {
type = types.listOf types.str;
default = [
"ldaps://account.skynet.ie"
"ldaps://sso.skynet.ie"
];
description = lib.mdDoc "ldap domains";
};
@ -197,233 +85,93 @@ in {
default = "cn=admin,${cfg.ldap.base}";
description = lib.mdDoc "where to find users";
};
};
};
config = mkIf cfg.enable {
services.skynet.backup.normal.backups = [
#"/var/vmail"
services.skynet_backup.normal.backups = [
"/var/vmail"
"/var/dkim"
];
age.secrets.ldap_pw.file = ../secrets/ldap/pw.age;
security.acme.certs = {
"mail" = {
domain = "mail.skynet.ie";
extraDomainNames = [
"imap.skynet.ie"
"pop3.skynet.ie"
"smtp.skynet.ie"
];
};
# set up dns record for it
skynet_dns.records = [
# basic one
{record="mail"; r_type="A"; value=cfg.host.ip;}
"imap" = {
domain = "imap.skynet.ie";
extraDomainNames = [
"mail.skynet.ie"
"pop3.skynet.ie"
"smtp.skynet.ie"
];
};
# TXT records, all tehse are inside escaped strings to allow using ""
# SPF record
{record="${cfg.domain}."; r_type="TXT"; value=''"v=spf1 a:${cfg.sub}.${cfg.domain} -all"'';}
# DKIM keys
{record="mail._domainkey.skynet.ie."; r_type="TXT"; value=''"v=DKIM1; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxju1Ie60BdHwyFVPNQKovL/cX9IFPzBKgjnHZf+WBzDCFKSBpf7NvnfXajtFDQN0poaN/Qfifid+V55ZCNDBn8Y3qZa4Y69iNiLw2DdvYf0HdnxX6+pLpbmj7tikGGLJ62xnhkJhoELnz5gCOhpyoiv0tSQVaJpaGZmoll861/QIDAQAB"'';}
{record="mail._domainkey.ulcompsoc.ie."; r_type="TXT"; value=''"v=DKIM1; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDl8ptSASx37t5sfmU2d2Y6yi9AVrsNFBZDmJ2uaLa4NuvAjxGQCw4wx+1Jui/HOuKYLpntLsjN851wgPR+3i51g4OblqBDvcHn9NYgWRZfHj9AASANQjdsaAbkXuyKuO46hZqeWlpESAcD6a4Evam4fkm+kiZC0+rccb4cWgsuLwIDAQAB"'';}
"pop3" = {
domain = "pop3.skynet.ie";
extraDomainNames = [
"imap.skynet.ie"
"mail.skynet.ie"
"smtp.skynet.ie"
];
};
# DMARC
{record="_dmarc.${cfg.domain}."; r_type="TXT"; value=''"v=DMARC1; p=none"'';}
"smtp" = {
domain = "smtp.skynet.ie";
extraDomainNames = [
"imap.skynet.ie"
"pop3.skynet.ie"
"mail.skynet.ie"
];
};
};
# 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}";}
];
# to provide the certs
services.nginx.virtualHosts = {
"mail.skynet.ie" = {
forceSSL = true;
useACMEHost = "mail";
"${cfg.sub}.${cfg.domain}" = {
forceSSL = true;
useACMEHost = "skynet";
# override the inbuilt nginx config
enableACME = false;
serverName = "mail.skynet.ie";
};
"imap.skynet.ie" = {
forceSSL = true;
useACMEHost = "imap";
# override the inbuilt nginx config
enableACME = false;
serverName = "imap.skynet.ie";
};
"pop3.skynet.ie" = {
forceSSL = true;
useACMEHost = "pop3";
# override the inbuilt nginx config
enableACME = false;
serverName = "pop3.skynet.ie";
};
"smtp.skynet.ie" = {
forceSSL = true;
useACMEHost = "smtp";
# override the inbuilt nginx config
enableACME = false;
serverName = "smtp.skynet.ie";
serverName = "${cfg.sub}.${cfg.domain}";
};
};
# set up dns record for it
services.skynet.dns.records =
[
# core record
{
record = "@";
r_type = "MX";
# the number is the priority in teh case of multiple mailservers
value = "10 mail.${cfg.domain}.";
}
# basic one
{
record = "mail";
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
++ [
{
record = "${cfg.domain}.";
r_type = "TXT";
value = ''"v=spf1 a:${cfg.sub}.${cfg.domain} ip4:${config.services.skynet.host.ip} -all"'';
}
]
# DKIM keys
++ [
{
record = "mail._domainkey.skynet.ie.";
r_type = "TXT";
value = ''"v=DKIM1; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxju1Ie60BdHwyFVPNQKovL/cX9IFPzBKgjnHZf+WBzDCFKSBpf7NvnfXajtFDQN0poaN/Qfifid+V55ZCNDBn8Y3qZa4Y69iNiLw2DdvYf0HdnxX6+pLpbmj7tikGGLJ62xnhkJhoELnz5gCOhpyoiv0tSQVaJpaGZmoll861/QIDAQAB"'';
}
{
domain = "ulcompsoc.ie";
record = "mail._domainkey.ulcompsoc.ie.";
r_type = "TXT";
value = ''"v=DKIM1; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDl8ptSASx37t5sfmU2d2Y6yi9AVrsNFBZDmJ2uaLa4NuvAjxGQCw4wx+1Jui/HOuKYLpntLsjN851wgPR+3i51g4OblqBDvcHn9NYgWRZfHj9AASANQjdsaAbkXuyKuO46hZqeWlpESAcD6a4Evam4fkm+kiZC0+rccb4cWgsuLwIDAQAB"'';
}
]
# DMARC
++ [
{
record = "_dmarc.${cfg.domain}.";
r_type = "TXT";
# p : quarantine => sends to spam, reject => never sent
# rua : mail that receives reports about DMARC activity
# pct : percentage of unathenticated messages that DMARC stops
# 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
# 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=quarantine"'';
}
];
#https://nixos-mailserver.readthedocs.io/en/latest/add-roundcube.html
users.groups.nginx = {};
users.groups.roundcube = {};
services.roundcube = {
enable = true;
# this is the url of the vhost, not necessarily the same as the fqdn of
# the mailserver
hostName = "${cfg.sub}.${cfg.domain}";
extraConfig = ''
enable = true;
# this is the url of the vhost, not necessarily the same as the fqdn of
# the mailserver
hostName = "${cfg.sub}.${cfg.domain}";
extraConfig = ''
# starttls needed for authentication, so the fqdn required to match
# the certificate
$config['smtp_server'] = "ssl://${cfg.sub}.${cfg.domain}";
$config['smtp_user'] = "%u";
$config['smtp_pass'] = "%p";
$config['imap_host'] = "ssl://${cfg.sub}.${cfg.domain}";
$config['product_name'] = "Skynet Webmail";
$config['identities_level'] = 4;
$config['login_username_filter'] = "email";
$config['ldap_public']['public'] = array(
'name' => 'Public LDAP Addressbook',
'hosts' => 'tls://account.skynet.ie',
'port' => 636 ,
'user_specific' => false,
'base_dn' => 'ou=users,dc=skynet,dc=ie',
'filter' => '(skMemberOf=cn=skynet-users-linux,ou=groups,dc=skynet,dc=ie)',
'fieldmap' => [
// Roundcube => LDAP:limit
'name' => 'cn',
'surname' => 'sn',
'email' => 'skMail:*',
]
);
'';
$config['imap_host'] = "ssl://${cfg.sub}.${cfg.domain}";
$config['product_name'] = "Skynet Webmail";
$config['identities_level'] = 4;
$config['login_username_filter'] = "email";
$config['ldap_public']['public'] = array(
'name' => 'Public LDAP Addressbook',
'hosts' => array('sso.skynet.ie'),
'port' => 636 ,
'user_specific' => false,
'base_dn' => 'ou=users,dc=skynet,dc=ie',
'filter' => '(skMemberOf=cn=skynet-users-linux,ou=groups,dc=skynet,dc=ie)',
'fieldmap' => [
// Roundcube => LDAP:limit
'name' => 'cn',
'surname' => 'sn',
'email' => 'skMail:*',
]
);
'';
};
# for https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/issues/275
services.dovecot2.sieve.extensions = ["fileinto"];
mailserver = {
enable = true;
fqdn = "${cfg.sub}.${cfg.domain}";
@ -431,12 +179,6 @@ in {
cfg.domain
];
enableManageSieve = true;
lmtpSaveToDetailMailbox = "yes";
extraVirtualAliases = create_skynet_service_mailboxes;
# use the letsencrypt certs
certificateScheme = "acme";
@ -461,7 +203,7 @@ in {
userAttrs = "quotaEmail=quota_rule=*:bytes=%$,=quota_rule2=Trash:storage=+100M";
# accept emails in, but only allow access to paid up members
passFilter = "(&(|${create_filter cfg.groups})(skMail=%u))";
passFilter = "(&(|${create_filter cfg.groups})(skMail=%u))";
};
postfix = {
@ -469,48 +211,14 @@ in {
uidAttribute = "skMail";
mailAttribute = "skMail";
};
};
# feckin spammers
rejectRecipients = [
];
};
services.dovecot2.sieve.scripts = {
before = sieveConfigFile;
};
# 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

View file

@ -1,9 +1,5 @@
{
lib,
pkgs,
config,
...
}: {
{lib, pkgs, config, ...}: {
# using https://github.com/greaka/ops/blob/818be4c4dea9129abe0f086d738df4cb0bb38288/apps/restic/options.nix as a base
options = {
skynet_firewall = {
@ -14,7 +10,7 @@
type = lib.types.bool;
};
forward = lib.mkOption {
default = [];
default = [ ];
type = lib.types.listOf lib.types.str;
description = ''
A list of routes to forward
@ -23,16 +19,16 @@
own = {
ip = lib.mkOption {
default = "127.0.0.1";
type = lib.types.str;
description = ''
IP of the firewall
'';
default = "127.0.0.1";
type = lib.types.str;
description = ''
IP of the firewall
'';
};
ports = {
tcp = lib.mkOption {
default = [];
default = [ ];
type = lib.types.listOf lib.types.int;
description = ''
A list of TCP ports for the machiene running the firewall
@ -40,13 +36,15 @@
};
udp = lib.mkOption {
default = [];
default = [ ];
type = lib.types.listOf lib.types.int;
description = ''
A list of UDP ports for the machiene running the firewall
'';
};
};
};
};
};
@ -58,7 +56,8 @@
# fules for the firewall
# beware of EOL conversion.
networking.nftables.ruleset = ''
networking.nftables.ruleset =
''
# using https://oxcrag.net/2021/12/25/build-your-own-router-with-nftables-part-1/ as a guide
# Clear out any existing rules
@ -165,6 +164,9 @@
}
}
'';
'';
};
}

68
applications/games.nix Normal file
View file

@ -0,0 +1,68 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.skynet_games;
in {
imports = [
./dns.nix
./games/minecraft.nix
];
options.services.skynet_games = {
enable = mkEnableOption "Skynet Games";
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 = "games";
};
};
};
config = mkIf cfg.enable {
skynet_dns.records = [
# need a base domain
{record=cfg.domain.sub; r_type="CNAME"; value=cfg.host.name;}
];
# the minecraft servers
services.skynet_games_minecraft = {
enable = true;
host = {
ip = cfg.host.ip;
name = cfg.domain.sub;
};
domain = {
sub = "minecraft.${cfg.domain.sub}";
};
};
};
}

View file

@ -1,60 +1,142 @@
{
config,
pkgs,
lib,
inputs,
...
}: let
# function to create the cname record for eachs erver
create_cname = configs:
lib.lists.forEach configs (
c: {
record = "${c.address}.games";
r_type = "CNAME";
value = config.services.skynet.host.name;
}
);
{ config, pkgs, lib, inputs, ... }:
with lib;
let
cfg = config.services.skynet_games_minecraft;
# function to create the srv record
# this allows us to change the port without impacting (java) users
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.";
});
# 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 {
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 {
imports = [
../acme.nix
../dns.nix
../firewall.nix
../nginx.nix
inputs.arion.nixosModules.arion
];
config = {
services.skynet.dns.records = (create_cname servers) ++ (create_srv servers);
options.services.skynet_games_minecraft = {
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_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;}
];
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"
];
};
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"
];
};
};
};
};
};
}

View file

@ -1,129 +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 = ''
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";
};
# 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,159 +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";
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;
};
};
};
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 = ../../secrets/forgejo/runners/token.age;
owner = cfg.runner.user;
group = cfg.runner.user;
};
# make sure the ssh config stuff is in teh right palce
systemd.tmpfiles.rules = [
#"d /home/${cfg.runner.user} 0755 ${cfg.runner.user} ${cfg.runner.user}"
"L+ /home/${cfg.runner.user}/.ssh/config 0755 ${cfg.runner.user} ${cfg.runner.user} - ${./ssh_config}"
];
age.secrets.forgejo_runner_ssh = {
file = ../../secrets/forgejo/runners/ssh.age;
mode = "600";
owner = "${cfg.runner.user}";
group = "${cfg.runner.user}";
symlink = false;
path = "/home/${cfg.runner.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.runner.user;
};
users = {
groups."${cfg.runner.user}" = {};
users."${cfg.runner.user}" = {
#isSystemUser = true;
isNormalUser = true;
group = cfg.runner.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.runner.name;
url = cfg.runner.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

@ -1,22 +1,28 @@
{
config,
pkgs,
lib,
...
}:
with lib; let
name = "gitlab";
cfg = config.services.skynet."${name}";
domain_base = "${cfg.domain.base}.${cfg.domain.tld}";
domain_full = "${cfg.domain.sub}.${domain_base}";
in {
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.skynet_gitlab;
in {
imports = [
./acme.nix
./dns.nix
./firewall.nix
./nginx.nix
];
options.services.skynet."${name}" = {
options.services.skynet_gitlab = {
enable = mkEnableOption "Skynet Gitlab";
host = {
ip = mkOption {
type = types.str;
};
name = mkOption {
type = types.str;
};
};
domain = {
tld = mkOption {
type = types.str;
@ -30,13 +36,12 @@ in {
sub = mkOption {
type = types.str;
default = name;
default = "gitlab";
};
};
user = mkOption {
type = types.str;
# changes teh ssh user
default = "git";
};
@ -46,7 +51,9 @@ in {
default = "dc=skynet,dc=ie";
description = lib.mdDoc "The base address in the ldap server";
};
};
};
config = mkIf cfg.enable {
@ -56,77 +63,41 @@ in {
# grep -r --exclude-dir={docker,containers,log,sys,nix,proc} gitlab /
age.secrets.gitlab_pw = {
file = ../../secrets/gitlab/pw.age;
file = ../secrets/gitlab/pw.age;
owner = cfg.user;
group = cfg.user;
};
age.secrets.gitlab_secrets_db = {
file = ../../secrets/gitlab/secrets_db.age;
file = ../secrets/gitlab/secrets_db.age;
owner = cfg.user;
group = cfg.user;
};
age.secrets.gitlab_secrets_secret = {
file = ../../secrets/gitlab/secrets_secret.age;
file = ../secrets/gitlab/secrets_secret.age;
owner = cfg.user;
group = cfg.user;
};
age.secrets.gitlab_secrets_otp = {
file = ../../secrets/gitlab/secrets_otp.age;
file = ../secrets/gitlab/secrets_otp.age;
owner = cfg.user;
group = cfg.user;
};
age.secrets.gitlab_secrets_jws = {
file = ../../secrets/gitlab/secrets_jws.age;
file = ../secrets/gitlab/secrets_jws.age;
owner = cfg.user;
group = cfg.user;
};
age.secrets.gitlab_db_pw = {
file = ../../secrets/gitlab/db_pw.age;
file = ../secrets/gitlab/db_pw.age;
owner = cfg.user;
group = cfg.user;
};
services.skynet.acme.domains = [
"${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}"
# Lets Encrypt seems to have a 4 levels limit for certs
"*.pages.${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 = "A";
value = config.services.skynet.host.ip;
}
skynet_dns.records = [
{record=cfg.domain.sub; r_type="CNAME"; value=cfg.host.name;}
# for gitlab pages
{
record = "*.pages.${cfg.domain.base}.${cfg.domain.tld}.";
r_type = "A";
value = config.services.skynet.host.ip;
}
# for email
{
record = "${cfg.domain.sub}";
r_type = "MX";
value = ''10 ${domain_full}.'';
}
{
record = config.services.skynet.host.ip;
r_type = "PTR";
value = "${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}.";
}
{
record = "${domain_full}.";
r_type = "TXT";
value = ''"v=spf1 a:gitlab.skynet.ie -all"'';
}
{
record = "_dmarc.${domain_full}.";
r_type = "TXT";
value = ''"v=DMARC1; p=none"'';
}
{record="*.pages.${cfg.domain.base}.${cfg.domain.tld}."; r_type="A"; value=cfg.host.ip;}
];
networking.firewall.allowedTCPPorts = [
@ -134,19 +105,14 @@ in {
2222
];
services.openssh.ports = [22 2222];
services.openssh.ports = [ 22 2222 ];
services.nginx.virtualHosts = {
# main site
"${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/" = {
proxyPass = "http://unix:/run/gitlab/gitlab-workhorse.socket";
extraConfig = ''
client_max_body_size 1000M;
'';
};
locations."/".proxyPass = "http://unix:/run/gitlab/gitlab-workhorse.socket";
};
# pages
@ -157,13 +123,6 @@ in {
};
};
# set a valid HELO address
services.postfix = {
hostname = lib.mkForce domain_full;
origin = lib.mkForce domain_full;
domain = lib.mkForce domain_base;
};
services.gitlab = {
enable = true;
@ -197,11 +156,13 @@ in {
auth-server = "https://gitlab.example.com";
*/
};
};
# use the local email client
smtp.enable = true;
#smtp = {
# enable = true;
# address = "localhost";
# port = 25;
#};
secrets = {
dbFile = config.age.secrets.gitlab_secrets_db.path;
secretFile = config.age.secrets.gitlab_secrets_secret.path;
@ -218,7 +179,7 @@ in {
servers = {
main = {
label = "Skynet";
host = "account.skynet.ie";
host = "sso.skynet.ie";
port = 636;
uid = "uid";
encryption = "simple_tls";
@ -232,7 +193,7 @@ in {
name = "cn";
};
group_base = "ou=groups,${cfg.ldap.base}";
group_base= "ou=groups,${cfg.ldap.base}";
admin_group = "skynet-admins";
sync_ssh_keys = "sshPublicKey";
@ -244,9 +205,9 @@ in {
# default for pages is set to 8090 but that leaves an "ugly" port in the url,
# override it here to make it look good
port = 80;
#external_http = ["${config.services.skynet.host.ip}:80"];
#external_http = ["${cfg.host.ip}:80"];
};
};
};
};
}
}

View file

@ -0,0 +1,103 @@
{ 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:latest";
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."${cfg.runner.name}".file = ../secrets/gitlab/runners/${cfg.runner.name}.age;
boot.kernel.sysctl."net.ipv4.ip_forward" = true; # 1
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
"${cfg.runner.name}" = {
cloneUrl = cfg.runner.gitlab;
description = cfg.runner.description;
registrationConfigFile = config.age.secrets."${cfg.runner.name}".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-23.05 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";
};
};
};
};
};
}

View file

@ -1,79 +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.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

@ -1,27 +1,37 @@
/*
Gonna use a priper nixos module for this
*/
{
config,
pkgs,
lib,
inputs,
...
}:
with lib; let
name = "ldap";
cfg = config.services.skynet."${name}";
domain = "${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}";
in {
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.skynet_ldap;
in {
# these are needed for teh program in question
imports = [
./acme.nix
./dns.nix
./nginx.nix
./ldap/ldap_backend.nix
];
options.services.skynet."${name}" = {
options.services.skynet_ldap = {
# options that need to be passed in to make this work
enable = mkEnableOption "Skynet LDAP service";
host = {
ip = mkOption {
type = types.str;
};
name = mkOption {
type = types.str;
};
};
domain = {
tld = mkOption {
type = types.str;
@ -35,7 +45,7 @@ in {
sub = mkOption {
type = types.str;
default = "account";
default = "sso";
};
};
@ -51,24 +61,24 @@ in {
};
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
age.secrets.ldap_pw = {
file = ../../secrets/ldap/pw.age;
file = ../secrets/ldap/pw.age;
mode = "440";
owner = "openldap";
group = "openldap";
};
services.skynet.acme.domains = [
domain
];
services.skynet.dns.records = [
{
record = cfg.domain.sub;
r_type = "CNAME";
value = config.services.skynet.host.name;
}
skynet_dns.records = [
{record=cfg.domain.sub; r_type="CNAME"; value=cfg.host.name;}
];
# firewall on teh computer itself
@ -77,49 +87,28 @@ in {
636
];
services.nginx.virtualHosts = {
${domain} = {
forceSSL = true;
useACMEHost = "skynet";
locations."/" = {
root = "${inputs.skynet_ldap_frontend.defaultPackage."x86_64-linux"}";
# https://stackoverflow.com/a/38238001
extraConfig = ''
if ($request_uri ~ ^/(.*)\.html) {
return 302 /$1;
}
try_files $uri $uri.html $uri/ =404;
'';
};
};
};
# using https://nixos.wiki/wiki/OpenLDAP for base config
systemd.services.openldap = {
wants = ["acme-${cfg.domain.base}.service"];
after = ["acme-${cfg.domain.base}.service"];
wants = [ "acme-${cfg.domain.base}.service" ];
after = [ "acme-${cfg.domain.base}.service" ];
};
users.groups.acme.members = ["openldap"];
users.groups.acme.members = [ "openldap" ];
services.openldap = {
# backup /var/lib/openldap/slapd.d
enable = true;
/*
enable plain and secure connections
*/
urlList = ["ldap:///" "ldaps:///"];
/* enable plain and secure connections */
urlList = [ "ldap:///" "ldaps:///" ];
settings = {
attrs = {
olcLogLevel = "conns config";
/*
settings for acme ssl
*/
/* settings for acme ssl */
olcTLSCACertificateFile = "/var/lib/acme/${cfg.domain.base}/full.pem";
olcTLSCertificateFile = "/var/lib/acme/${cfg.domain.base}/cert.pem";
olcTLSCertificateKeyFile = "/var/lib/acme/${cfg.domain.base}/key.pem";
@ -140,78 +129,68 @@ in {
"${pkgs.openldap}/etc/schema/cosine.ldif"
"${pkgs.openldap}/etc/schema/inetorgperson.ldif"
"${pkgs.openldap}/etc/schema/nis.ldif"
./openssh-lpk.ldif
./skMemberOf.ldif
./ldap/openssh-lpk.ldif
./ldap/skMemberOf.ldif
];
"cn=modules".attrs = {
objectClass = ["olcModuleList"];
cn = "modules";
objectClass = [ "olcModuleList" ];
cn = "modules";
olcModuleLoad = ["dynlist" "memberof" "refint" "pw-sha2"];
};
"olcDatabase={-1}frontend".attrs = {
objectClass = ["olcDatabaseConfig" "olcFrontendConfig"];
objectClass = [ "olcDatabaseConfig" "olcFrontendConfig" ];
olcPasswordHash = "{SSHA512}";
};
"olcDatabase={1}mdb" = {
attrs = {
objectClass = ["olcDatabaseConfig" "olcMdbConfig"];
objectClass = [ "olcDatabaseConfig" "olcMdbConfig" ];
olcDatabase = "{1}mdb";
olcDbDirectory = "/var/lib/openldap/data";
olcSuffix = cfg.base;
/*
your admin account, do not use writeText on a production system
*/
/* your admin account, do not use writeText on a production system */
olcRootDN = "cn=admin,${cfg.base}";
olcRootPW.path = config.age.secrets.ldap_pw.path;
#olcOverlay = "memberof";
olcAccess = [
/*
custom access rules for userPassword attributes
*/
''
{0}to attrs=userPassword
by dn.exact="uid=ldap_api,ou=users,dc=skynet,dc=ie" manage
/* custom access rules for userPassword attributes */
''{0}to attrs=userPassword
by self write
by anonymous auth
by * none
''
by * none''
''
{1}to attrs=mail,sshPublicKey,cn,sn
by dn.exact="uid=ldap_api,ou=users,dc=skynet,dc=ie" manage
''{1}to attrs=mail,sshPublicKey,cn,sn,skDiscord
by self write
by * read
''
by * read''
/*
allow read on anything else
*/
''
{2}to *
by dn.exact="uid=ldap_api,ou=users,dc=skynet,dc=ie" manage
by * read
''
/* allow read on anything else */
''{2}to *
by * read''
];
};
# https://blog.oddbit.com/post/2013-07-22-generating-a-membero/
children = {
"olcOverlay=dynlist".attrs = {
objectClass = ["olcOverlayConfig" "olcDynamicList"];
olcOverlay = "dynlist";
objectClass = [ "olcOverlayConfig" "olcDynamicList" ];
olcOverlay = "dynlist";
olcDlAttrSet = "skPerson labeledURI skMemberOf";
};
"olcOverlay=memberof".attrs = {
objectClass = ["olcOverlayConfig" "olcMemberOf" "olcConfig" "top"];
olcOverlay = "memberof";
objectClass = [ "olcOverlayConfig" "olcMemberOf" "olcConfig" "top" ];
olcOverlay = "memberof";
olcMemberOfDangling = "ignore";
olcMemberOfRefInt = "TRUE";
@ -220,9 +199,12 @@ in {
olcMemberOfMemberOfAD = "memberOf";
};
};
};
};
};
};
};
}
}

View file

@ -1,79 +0,0 @@
{
config,
pkgs,
lib,
inputs,
...
}:
with lib; let
name = "ldap_backend";
cfg = config.services.skynet."${name}";
port_backend = "8087";
in {
imports = [
inputs.skynet_ldap_backend.nixosModule."x86_64-linux"
../../config/users.nix
];
options.services.skynet."${name}" = {
enable = mkEnableOption "Skynet LDAP backend server";
domain = {
tld = mkOption {
type = types.str;
default = "ie";
};
base = mkOption {
type = types.str;
default = "skynet";
};
sub = mkOption {
type = types.str;
default = "api.account";
};
};
};
config = mkIf cfg.enable {
#backups = [ "/etc/silver_ul_ical/database.db" ];
age.secrets.ldap_details.file = ../../secrets/ldap/details.age;
age.secrets.ldap_mail.file = ../../secrets/email/details.age;
age.secrets.ldap_wolves.file = ../../secrets/wolves/details.age;
services.skynet.acme.domains = [
"${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}"
];
services.skynet.dns.records = [
{
record = cfg.domain.sub;
r_type = "CNAME";
value = config.services.skynet.host.name;
}
];
services.nginx.virtualHosts."${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/".proxyPass = "http://localhost:${port_backend}";
};
# this got imported
services.skynet_ldap_backend = {
enable = true;
# contains teh password in env form
env = {
ldap = config.age.secrets.ldap_details.path;
mail = config.age.secrets.ldap_mail.path;
wolves = config.age.secrets.ldap_wolves.path;
};
host_port = "127.0.0.1:${port_backend}";
users = config.skynet.users;
};
};
}

View file

@ -1,138 +0,0 @@
{
config,
pkgs,
lib,
...
}:
with lib; let
name = "ldap_client";
cfg = config.services.skynet."${name}";
# always ensure the admin group has access
create_filter_check_admin = x:
if !(builtins.elem "skynet-admins" x)
then x ++ ["skynet-admins"]
else x;
# create teh new strings
create_filter_array = map (x: "(skMemberOf=cn=${x},ou=groups,${cfg.base})");
create_filter_join = x: concatStringsSep "" x;
# thought you could escape racket?
create_filter = x: create_filter_join (create_filter_array (create_filter_check_admin x));
sudo_create_filter = x: (concatStringsSep ", " (map (x: "cn=${x},ou=groups,${cfg.base}") x));
in {
# these are needed for teh program in question
imports = [];
# give users access to this server
#services.skynet.ldap_client.groups = ["skynet-users-linux"];
options.services.skynet."${name}" = {
# options that need to be passed in to make this work
enable = mkEnableOption "Skynet LDAP client";
address = mkOption {
type = types.str;
default = "account.skynet.ie";
description = lib.mdDoc "The domain the ldap is behind";
};
base = mkOption {
type = types.str;
default = "dc=skynet,dc=ie";
description = lib.mdDoc "The base address in the ldap server";
};
groups = mkOption {
type = types.listOf types.str;
default = [
"skynet-admins-linux"
];
description = lib.mdDoc "Groups we want to allow access to the server";
};
sudo_groups = mkOption {
type = types.listOf types.str;
default = [
"skynet-admins-linux"
];
description = lib.mdDoc "Groups we want to allow access to the server";
};
};
config = mkIf cfg.enable {
# this is athe actual configuration that we need to do
security.sudo.extraRules = [
# admin group has sudo access
{
groups = cfg.sudo_groups;
commands = [
{
command = "ALL";
options = ["NOPASSWD"];
}
];
}
];
# give users a home dir
security.pam.services.sshd.makeHomeDir = true;
services.openssh = {
# only allow ssh keys
settings.PasswordAuthentication = false;
# tell users where tehy cna setup their ssh key
banner = ''
If you get 'Permission denied (publickey,keyboard-interactive)' you need to add an ssh key on https://${cfg.address}
'';
};
services.sssd = {
enable = true;
sshAuthorizedKeysIntegration = true;
config = ''
[domain/skynet.ie]
id_provider = ldap
auth_provider = ldap
sudo_provider = ldap
ldap_uri = ldaps://${cfg.address}:636
ldap_search_base = ${cfg.base}
# thank ye https://medium.com/techish-cloud/linux-user-ssh-authentication-with-sssd-ldap-without-joining-domain-9151396d967d
ldap_user_search_base = ou=users,${cfg.base}?sub?(|${create_filter cfg.groups})
ldap_group_search_base = ou=groups,${cfg.base}
# using commas from https://support.hpe.com/hpesc/public/docDisplay?docId=c02793175&docLocale=en_US
ldap_sudo_search_base, ${sudo_create_filter cfg.sudo_groups}
ldap_group_nesting_level = 5
cache_credentials = false
entry_cache_timeout = 1
ldap_user_member_of = skMemberOf
[sssd]
config_file_version = 2
services = nss, pam, sudo, ssh
domains = skynet.ie
[nss]
# override_homedir = /home/%u
[pam]
[sudo]
[autofs]
'';
};
};
}

View file

@ -0,0 +1,90 @@
{ config, pkgs, lib, inputs, ... }:
with lib;
let
cfg = config.services.ldap_backend;
port_backend = "8087";
in {
imports = [
../acme.nix
../dns.nix
../nginx.nix
inputs.skynet_ldap_backend.nixosModule."x86_64-linux"
];
options.services.ldap_backend = {
enable = mkEnableOption "Skynet LDAP backend server";
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 = "api.sso";
};
};
};
config = mkIf cfg.enable {
#backups = [ "/etc/silver_ul_ical/database.db" ];
age.secrets.ldap_self_service.file = ../../secrets/ldap/self_service.age;
skynet_dns.records = [
{record=cfg.domain.sub; r_type="CNAME"; value=cfg.host.name;}
];
services.nginx.virtualHosts."${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/".proxyPass = "http://localhost:${port_backend}";
};
services.skynet_ldap_backend = {
enable = true;
# contains teh password in env form
envFile = config.age.secrets.ldap_self_service.path;
ldap = {
host = "ldaps://sso.skynet.ie";
admin = "cn=admin,dc=skynet,dc=ie";
};
users = {
admin = [
"silver"
"evanc"
"eoghanconlon73"
];
committee = [
"silver"
"eoghanconlon73"
];
lifetime = [];
banned = [];
};
host_port = "127.0.0.1:${port_backend}";
};
};
}

View file

@ -24,12 +24,24 @@ olcAttributeTypes: ( 1.3.6.1.4.1.24441.1.4.1
EQUALITY caseIgnoreMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
olcAttributeTypes: ( 1.3.6.1.4.1.24441.1.5.1
NAME 'skDiscord'
DESC 'Discord username'
EQUALITY caseIgnoreMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
olcAttributeTypes: ( 1.3.6.1.4.1.24441.1.6.1
NAME 'skCreated'
DESC 'When the account was created'
EQUALITY caseIgnoreMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#olcAttributeTypes: ( 1.3.6.1.4.1.24441.1.7.1
# NAME 'skEnabled'
# DESC 'TRUE/FALSE'
# EQUALITY booleanMatch
# SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
# )
# https://github.com/variablenix/ldap-mail-schema/blob/master/quota.schema
olcAttributeTypes: ( 1.3.6.1.4.1.24441.1.8.1
NAME 'quotaEmail'
@ -43,10 +55,16 @@ olcAttributeTypes: ( 1.3.6.1.4.1.24441.1.9.1
EQUALITY caseIgnoreIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{255}
)
olcAttributeTypes: ( 1.3.6.1.4.1.24441.1.10.1
NAME 'skSecure'
DESC '1 if secure'
EQUALITY caseIgnoreMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
olcObjectClasses: ( 1.3.6.1.4.1.24441.1.1.1
NAME 'skPerson'
DESC 'skynet person'
SUP top AUXILIARY
MUST ( skMail $ skCreated )
MAY ( skMemberOf $ skID $ quotaEmail $ quotaDisk )
MAY ( skMemberOf $ skID $ skDiscord $ quotaEmail $ quotaDisk $ skSecure )
)

View file

@ -0,0 +1,117 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.skynet_ldap_client;
# always ensure the admin group has access
create_filter_check_admin = (x: if !(builtins.elem "skynet-admins" x) then x ++ ["skynet-admins"] else x);
# create teh new strings
create_filter_array = map (x: "(skMemberOf=cn=${x},ou=groups,${cfg.base})");
create_filter_join = (x: concatStringsSep "" x);
# thought you could escape racket?
create_filter = (x: create_filter_join (create_filter_array (create_filter_check_admin x) ) );
in {
# these are needed for teh program in question
imports = [];
# give users access to this server
#services.skynet_ldap_client.groups = ["skynet-users-linux"];
options.services.skynet_ldap_client = {
# options that need to be passed in to make this work
enable = mkEnableOption "Skynet LDAP client";
address = mkOption {
type = types.str;
default = "sso.skynet.ie";
description = lib.mdDoc "The domain the ldap is behind";
};
base = mkOption {
type = types.str;
default = "dc=skynet,dc=ie";
description = lib.mdDoc "The base address in the ldap server";
};
groups = mkOption {
type = types.listOf types.str;
default = [
"skynet-admins-linux"
];
description = lib.mdDoc "Groups we want to allow access to the server";
};
};
config = mkIf cfg.enable {
# this is athe actual configuration that we need to do
security.sudo.extraRules = [
# admin group has sudo access
{ groups = [ "skynet-admins-linux" ]; commands = [ { command = "ALL"; options = [ "NOPASSWD" ]; } ]; }
];
# give users a home dir
security.pam.services.sshd.makeHomeDir = true;
services.openssh = {
# only allow ssh keys
settings.PasswordAuthentication = false;
# tell users where tehy cna setup their ssh key
banner = ''
If you get 'Permission denied (publickey,keyboard-interactive)' you need to add an ssh key on https://${cfg.address}
'';
};
services.sssd = {
enable = true;
sshAuthorizedKeysIntegration = true;
config = ''
[domain/skynet.ie]
id_provider = ldap
auth_provider = ldap
sudo_provider = ldap
ldap_uri = ldaps://${cfg.address}:636
ldap_search_base = ${cfg.base}
# thank ye https://medium.com/techish-cloud/linux-user-ssh-authentication-with-sssd-ldap-without-joining-domain-9151396d967d
ldap_user_search_base = ou=users,${cfg.base}?sub?(|${create_filter cfg.groups})
ldap_group_search_base = ou=groups,${cfg.base}
ldap_sudo_search_base = cn=skynet-admins-linux,ou=groups,${cfg.base}
ldap_group_nesting_level = 5
cache_credentials = false
entry_cache_timeout = 1
ldap_user_member_of = skMemberOf
[sssd]
config_file_version = 2
services = nss, pam, sudo, ssh
domains = skynet.ie
[nss]
# override_homedir = /home/%u
[pam]
[sudo]
[autofs]
'';
};
};
}

View file

@ -1,136 +0,0 @@
{
config,
lib,
pkgs,
...
}:
with lib; let
name = "nextcloud";
cfg = config.services.skynet."${name}";
domain = "${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}";
in {
imports = [
];
options.services.skynet."${name}" = {
enable = mkEnableOption "Skynet Nextcloud";
domain = {
tld = mkOption {
type = types.str;
default = "ie";
};
base = mkOption {
type = types.str;
default = "skynet";
};
sub = mkOption {
type = types.str;
default = name;
};
};
};
config = mkIf cfg.enable {
# shove the entire config file into secrets
age.secrets.nextcloud_admin_pass = {
file = ../secrets/nextcloud/pw.age;
owner = "nextcloud";
group = "nextcloud";
};
services.skynet.acme.domains = [
domain
"onlyoffice.${domain}"
"whiteboard.${domain}"
];
services.skynet.dns.records = [
{
record = cfg.domain.sub;
r_type = "CNAME";
value = config.services.skynet.host.name;
}
{
record = "onlyoffice.${cfg.domain.sub}";
r_type = "CNAME";
value = config.services.skynet.host.name;
}
{
record = "whiteboard.${cfg.domain.sub}";
r_type = "CNAME";
value = config.services.skynet.host.name;
}
];
# /var/lib/nextcloud/data
services.nextcloud = {
enable = true;
package = pkgs.nextcloud30;
hostName = domain;
https = true;
configureRedis = true;
database.createLocally = true;
config = {
dbtype = "pgsql";
adminpassFile = config.age.secrets.nextcloud_admin_pass.path;
};
appstoreEnable = true;
extraApps = {
inherit (config.services.nextcloud.package.packages.apps) richdocuments;
};
extraAppsEnable = true;
settings = {
trusted_proxies = ["193.1.99.65"];
default_phone_region = "IE";
mail_smtpmode = "sendmail";
mail_sendmailmode = "pipe";
};
};
environment.etc."nextcloud-whiteboard-secret".text = ''
JWT_SECRET_KEY=test123
'';
services.nextcloud-whiteboard-server = {
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 = {
${domain} = {
forceSSL = true;
useACMEHost = "skynet";
};
"onlyoffice.${domain}" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/".proxyPass = "http://127.0.0.1:8000";
};
"whiteboard.${domain}" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/" = {
proxyPass = "http://localhost:3002";
proxyWebsockets = true;
};
};
};
};
}

View file

@ -1,4 +1,5 @@
# using K900's one https://gitlab.com/K900/nix/-/blob/a69502b8bf39fd99a85342b2f7989fe5896a6ae0/applications/base/nginx.nix
{pkgs, ...}: {
services.nginx = {
enable = true;
@ -9,6 +10,8 @@
recommendedGzipSettings = true;
recommendedProxySettings = true;
statusPage = true;
# give Nginx access to our certs
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

@ -1,96 +0,0 @@
/*
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 Proxmox VE LXC module.";
};
privileged = mkOption {
type = types.bool;
default = false;
description = ''
Whether to enable privileged mounts
'';
};
manageNetwork = mkOption {
type = types.bool;
default = false;
description = ''
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 = ''
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;
};
console.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) [
{
enable = false;
where = "/sys/kernel/debug";
}
];
services."getty@".unitConfig.ConditionPathExists = ["" "/dev/%I"];
};
};
}

View file

@ -1,199 +1,199 @@
# nodes is all the nodes
{
lib,
config,
nodes,
pkgs,
...
}:
with lib; let
name = "backup";
cfg = config.services.skynet."${name}";
{ lib, config, nodes, pkgs, ...}: with lib;
let
cfg = config.services.skynet_backup;
enable_client = cfg.normal.backups != null && cfg.normal.backups != [];
# since they should all have the same config we can do this
base = {
paths = cfg.normal.backups;
exclude = cfg.normal.exclude;
initialize = true;
passwordFile = config.age.secrets.restic.path;
# since they should all have the same config we can do this
base = {
paths = cfg.normal.backups;
exclude = cfg.normal.exclude;
initialize = true;
passwordFile = config.age.secrets.restic.path;
pruneOpts = [
#"--keep-within 0y2m0d0h"
#"--keep-monthly 2"
];
pruneOpts = [
#"--keep-within 0y2m0d0h"
#"--keep-monthly 2"
];
timerConfig = {
OnCalendar = "daily";
Persistent = true;
RandomizedDelaySec = "5h";
timerConfig = {
OnCalendar = "daily";
Persistent = true;
RandomizedDelaySec = "5h";
};
};
};
# takes nodes,
# for each check if iut has teh abckup attribute,
# then if the server is enabled,
# then pull relevant dtails
ownServers = builtins.listToAttrs (builtins.concatLists (
lib.attrsets.mapAttrsToList (
key: value: let
backup = value.config.services.skynet.backup;
backup_host = value.config.services.skynet.host;
in
if
(
(builtins.hasAttr "backup" value.config.services.skynet)
&& backup.server.enable
# chgeck that its not itself
&& backup_host.name != config.services.skynet.host.name
&& !backup.server.appendOnly
)
# takes nodes,
# for each check if iut has teh abckup attribute,
# then if the server is enabled,
# then pull relevant dtails
ownServers = builtins.listToAttrs (builtins.concatLists (
lib.attrsets.mapAttrsToList (key: value:
let
backup = value.config.services.skynet_backup;
in
if (
(builtins.hasAttr "skynet_backup" value.config.services)
&& backup.server.enable
&& backup.host.name != cfg.host.name
&& !backup.server.appendOnly
)
then [
{
name = backup_host.name;
value =
base
// {
repositoryFile = "/etc/skynet/restic/${backup_host.name}";
name = backup.host.name;
value = base // {
repositoryFile = "/etc/skynet/restic/${backup.host.name}";
backupPrepareCommand = ''
#!${pkgs.stdenv.shell}
set -euo pipefail
backupPrepareCommand = ''
#!${pkgs.stdenv.shell}
set -euo pipefail
baseDir="/etc/skynet/restic"
baseDir="/etc/skynet/restic"
mkdir -p $baseDir
cd $baseDir
mkdir -p $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
#PW = `cat ${config.age.secrets.restic.path}`
line=$(head -n 1 ${config.age.secrets.restic.path})
# read in teh password
#PW = `cat ${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}
'';
};
}
]
else []
)
nodes
));
in {
imports = [
];
else [ ]
) nodes
));
# 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
# will eb enabled on every server
options.services.skynet."${name}" = {
enable = mkEnableOption "Skynet backup";
# what folders to backup
normal = {
backups = lib.mkOption {
default = [];
type = lib.types.listOf lib.types.str;
description = ''
A list of paths to backup.
'';
in {
imports = [
];
# 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
# will eb enabled on every server
options.services.skynet_backup = {
# backup is enabled by default
# enable = mkEnableOption "Skynet backup";
# what folders to backup
normal = {
backups = lib.mkOption {
default = [ ];
type = lib.types.listOf lib.types.str;
description = ''
A list of paths to backup.
'';
};
exclude = lib.mkOption {
default = [ ];
type = lib.types.listOf lib.types.str;
description = ''
A list of paths to exclide .
'';
};
};
exclude = lib.mkOption {
default = [];
type = lib.types.listOf lib.types.str;
description = ''
A list of paths to exclide .
'';
# append only data so space limited
secure = {
backups = lib.mkOption {
default = [ ];
type = lib.types.listOf lib.types.str;
description = ''
A list of paths to backup.
'';
};
exclude = lib.mkOption {
default = [ ];
type = lib.types.listOf lib.types.str;
description = ''
A list of paths to exclide .
'';
};
};
host = {
ip = mkOption {
type = types.str;
};
name = mkOption {
type = types.str;
};
};
server = {
enable = mkEnableOption "Skynet backup Server";
port = mkOption {
type = types.port;
default = 8765;
};
appendOnly = mkOption {
type = types.bool;
default = false;
};
};
};
# append only data so space limited
secure = {
backups = lib.mkOption {
default = [];
type = lib.types.listOf lib.types.str;
description = ''
A list of paths to backup.
'';
};
exclude = lib.mkOption {
default = [];
type = lib.types.listOf lib.types.str;
description = ''
A list of paths to exclide .
'';
};
config = {
# these values are anabled for every client
environment.systemPackages = [
# for flakes
pkgs.restic
];
# A list of all login accounts. To create the password hashes, use
# nix-shell -p apacheHttpd
# htpasswd -nbB "" "password" | cut -d: -f2
age.secrets.restic.file = ../secrets/backup/restic.age;
networking.firewall.allowedTCPPorts = [
cfg.server.port
];
services.restic.backups = ownServers // {
# merge teh two configs together
# backblaze = base // {
# # backupos for each server are stored in a folder under their name
# repository = "b2:NixOS-Main2:/${cfg.host.name}";
# #environmentFile = config.age.secrets.backblaze.path;
# };
};
server = {
enable = mkEnableOption "Skynet backup Server";
port = mkOption {
type = types.port;
default = 8765;
};
appendOnly = mkOption {
type = types.bool;
default = false;
};
age.secrets.restic_pw = mkIf cfg.server.enable {
file = ../secrets/backup/restic_pw.age;
path = "${config.services.restic.server.dataDir}/.htpasswd";
symlink = false;
mode = "770";
owner = "restic";
group = "restic";
};
services.restic.server = mkIf cfg.server.enable{
enable = true;
listenAddress = "${cfg.host.ip}:${toString cfg.server.port}";
appendOnly = cfg.server.appendOnly;
privateRepos = true;
};
};
config = mkMerge [
{
# these values are anabled for every client
environment.systemPackages = with pkgs; [
restic
];
}
(mkIf cfg.server.enable {
networking.firewall.allowedTCPPorts = [
cfg.server.port
];
age.secrets.restic_pw = {
file = ../secrets/backup/restic_pw.age;
path = "${config.services.restic.server.dataDir}/.htpasswd";
symlink = false;
mode = "770";
owner = "restic";
group = "restic";
};
services.restic.server = {
enable = true;
listenAddress = "${config.services.skynet.host.ip}:${toString cfg.server.port}";
appendOnly = cfg.server.appendOnly;
privateRepos = true;
};
})
(mkIf enable_client {
# client stuff here
# A list of all login accounts. To create the password hashes, use
# nix-shell -p apacheHttpd
# htpasswd -nbB "" "password" | cut -d: -f2
age.secrets.restic.file = ../secrets/backup/restic.age;
services.restic.backups = mkMerge [
ownServers
{
# merge teh two configs together
# backblaze = base // {
# # backupos for each server are stored in a folder under their name
# repository = "b2:NixOS-Main2:/${config.services.skynet.host.name}";
# #environmentFile = config.age.secrets.backblaze.path;
# };
}
];
})
];
}

View file

@ -0,0 +1,55 @@
{ 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_dns.records = [
# means root domain, so skynet.ie
{record="@"; r_type="A"; value=cfg.host.ip;}
{record="2016"; r_type="CNAME"; value="skynet.ie";}
];
networking.firewall.allowedTCPPorts = [80 443];
services.httpd = {
enable = true;
group = "acme";
virtualHosts = {
# main site
"skynet.ie" = {
forceSSL = true;
useACMEHost = "skynet";
documentRoot = "${inputs.skynet_website.defaultPackage."x86_64-linux"}";
# only on skynet.ie
# skynet.ie/~username
enableUserDir = true;
};
# archive of teh site as it was ~2012 to 2016
"2016.skynet.ie" = {
forceSSL = true;
useACMEHost = "skynet";
documentRoot = "${inputs.skynet_website_2016.defaultPackage."x86_64-linux"}";
};
};
};
};
}

View file

@ -1,34 +0,0 @@
{year}: {
config,
pkgs,
lib,
inputs,
...
}:
with lib; {
imports = [];
config = {
services.skynet.acme.domains = [
"${year}.skynet.ie"
];
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"}";
};
};
};
};
}

View file

@ -1,91 +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 = "2023";})
(import ./old_site.nix {year = "2017";})
(import ./old_site.nix {year = "2009";})
];
options.services.skynet."${name}" = {
enable = mkEnableOption "Skynet Main Website";
};
config = mkIf cfg.enable {
services.skynet.acme.domains = [
"www.skynet.ie"
"discord.skynet.ie"
"public.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 = "public";
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;
# 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;";
};
};
};
};
}

View file

@ -1,64 +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.acme.domains = [
"renew.skynet.ie"
"wiki.skynet.ie"
];
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

@ -1,138 +0,0 @@
{
config,
pkgs,
lib,
inputs,
...
}:
with lib; let
name = "website_users";
cfg = config.services.skynet."${name}";
php_pool = name;
in {
imports = [
];
options.services.skynet."${name}" = {
enable = mkEnableOption "Skynet User Linux Server";
};
config = {
# we havea more limited ports range on the skynet server
services.skynet.prometheus.ports = {
node = 9000;
};
# allow more than admins access
services.skynet.ldap_client = {
groups = [
"skynet-admins-linux"
"skynet-users-linux"
];
};
# Website config
services.skynet.acme.domains = [
"users.skynet.ie"
"*.users.skynet.ie"
];
services.skynet.dns.records = [
{
record = "users";
r_type = "CNAME";
value = config.services.skynet.host.name;
}
{
record = "*.users";
r_type = "CNAME";
value = config.services.skynet.host.name;
}
];
environment.systemPackages = with pkgs; [
vim
php
];
networking = {
defaultGateway = {
address = lib.mkDefault "193.1.96.161";
interface = lib.mkDefault "eth1";
};
};
# normally services cannot read home dirs
systemd.services.nginx.serviceConfig.ProtectHome = "read-only";
systemd.services."phpfpm-${php_pool}".serviceConfig.ProtectHome = lib.mkForce "read-only";
services.phpfpm.pools.${php_pool} = {
user = config.services.nginx.user;
group = config.services.nginx.group;
settings = {
"listen.owner" = config.services.nginx.user;
"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 = {
"outinul.ie" = {
forceSSL = true;
enableACME = true;
locations = {
"/" = {
alias = "/home/outinul/public_html/";
index = "index.html";
extraConfig = ''
autoindex on;
'';
tryFiles = "$uri$args $uri$args/ /index.html";
};
};
};
# main site
"*.users.skynet.ie" = {
forceSSL = true;
useACMEHost = "skynet";
serverName = "~^(?<user>.+)\.users\.skynet\.ie";
# username.users.skynet.ie/
# user goes:
# chmod 711 ~
# chmod -R 755 ~/public_html
locations = {
"/" = {
alias = "/home/$user/public_html/";
index = "index.html";
extraConfig = ''
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";
};
};
};
};
};
}

View file

@ -1,61 +1,63 @@
{
config,
lib,
pkgs,
...
}:
with lib; let
name = "ulfm";
cfg = config.services.skynet."${name}";
in {
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.skynet_ulfm;
in {
imports = [
./acme.nix
./dns.nix
./firewall.nix
./nginx.nix
];
options.services.skynet."${name}" = {
enable = mkEnableOption "ULFM service";
options.services.skynet_ulfm = {
enable = mkEnableOption "ULFM service";
domain = {
tld = mkOption {
type = types.str;
default = "ie";
};
host = {
ip = mkOption {
type = types.str;
};
base = mkOption {
type = types.str;
default = "skynet";
};
name = mkOption {
type = types.str;
};
};
sub = mkOption {
type = types.str;
default = "ulfm";
};
};
domain = {
tld = mkOption {
type = types.str;
default = "ie";
};
base = mkOption {
type = types.str;
default = "skynet";
};
sub = mkOption {
type = types.str;
default = "ulfm";
};
};
};
config = mkIf cfg.enable {
# TODO: extract this out into its own config
# shove the entire config file into secrets
age.secrets.ulfm.file = ../secrets/stream_ulfm.age;
networking.firewall.allowedTCPPorts = [
8000
];
services.skynet.acme.domains = [
"${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}"
];
services.skynet.dns.records = [
{
record = cfg.domain.sub;
r_type = "CNAME";
value = config.services.skynet.host.name;
}
skynet_dns.records = [
{record=cfg.domain.sub; r_type="CNAME"; value=cfg.host.name;}
];
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 8000 counter packets 0 bytes 0 accept"
"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 8000 counter packets 0 bytes 0 accept"
];
users.groups."icecast" = {};
@ -68,9 +70,9 @@ in {
};
systemd.services.icecast = {
after = ["network.target"];
after = [ "network.target" ];
description = "Icecast Network Audio Streaming Server";
wantedBy = ["multi-user.target"];
wantedBy = [ "multi-user.target" ];
preStart = "mkdir -p /var/log/icecast && chown nobody:nogroup /var/log/icecast";
serviceConfig = {
@ -80,14 +82,12 @@ in {
};
};
services.nginx = {
virtualHosts = {
"${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/".proxyPass = "http://localhost:8000";
};
};
services.nginx.virtualHosts."${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}" = {
forceSSL = true;
useACMEHost = "skynet";
locations."/".proxyPass = "http://localhost:8000";
};
};
}
}

View file

@ -1,59 +0,0 @@
{lib, ...}: {
imports = [
];
options.skynet.records = lib.mkOption {
description = "Records, sorted based on therir type";
type = lib.types.listOf (lib.types.submodule (import ../applications/dns/options-records.nix {
inherit lib;
}));
};
config = {
skynet.records =
[
# Proxmox hosts
{
record = "jarvis";
r_type = "A";
value = "193.1.99.73";
server = true;
}
{
record = "ultron";
r_type = "A";
value = "193.1.99.84";
server = true;
}
# wifi in server room
{
record = "ash";
r_type = "A";
value = "193.1.99.114";
server = true;
}
]
# 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.";
}
];
};
}

View file

@ -1,408 +0,0 @@
{
lib,
config,
...
}:
with lib; let
port_backend = "8087";
cfg = config.skynet.users;
in {
options.skynet = {
users = {
committee = mkOption rec {
type = types.listOf types.str;
default = [];
description = "array of committee members";
};
admin = mkOption rec {
type = types.listOf types.str;
default = [];
description = "array of admins";
};
trainee = mkOption rec {
type = types.listOf types.str;
default = [];
description = "array of trainee admins";
};
lifetime = mkOption rec {
type = types.listOf types.str;
default = [];
description = "array of lifetime users";
};
banned = mkOption rec {
type = types.listOf types.str;
default = [];
description = "array of banned users";
};
restricted = mkOption rec {
type = types.listOf types.str;
default = [];
description = "array of restricted user accounts";
};
clubs_societies = mkOption rec {
type = types.listOf types.str;
default = [];
description = "array of accounts for Clubs and Societies";
};
};
};
config.skynet = {
users = {
committee = lib.lists.unique (
# Committee - Core
[
"silver"
"eoghanconlon73"
"nanda"
"emily1999"
"dgr"
]
# Committee - OCM
++ [
"skyapples"
"eliza"
"amymucko"
"archiedms"
"kaiden"
]
# Committee - SISTEM
++ [
"peace"
]
# Admins are part of Committee as well
++ cfg.admin
);
admin = [
"silver"
"evanc"
"eliza"
"esy"
];
trainee = [];
lifetime = [];
banned = [];
clubs_societies = [
"outinul"
"gamesdev"
];
restricted =
[
# usernames folks arent allowed to use
"contact"
"dnsadm"
"president"
"treasurer"
"secretary"
"pro"
"sysadmin"
"root"
]
++ [
# basis comes from https://discord.com/channels/689189992417067052/1126084496710713414/1149072061466169444
# start off with compsoc stuff first
"competition_www"
"demo1"
"demouser"
"ftp"
"lost+found"
"postfix"
"skynews.old"
"system_backup"
"test"
"test12"
"test20202"
"test20203"
"tmp"
"webadm"
]
++ [
# clubs and socs (as far as I can tell
"aerosoc"
"aikido"
"anfocal"
"bics"
"boarding"
"cns"
"dev"
"filmsoc"
"gaa"
"german"
"golfsoc"
"handball"
"hispanic"
"history"
"hockey"
"home"
"legosoc"
"lifesave"
"mens_gfc"
"musicsoc"
"pagansoc"
"peacesoc"
"physics"
"poker"
"prolife"
"radio"
"ragweek"
"sinnfein"
"soccer"
"ulbs"
"ulcamogie"
"ulcc"
"ulgaa"
"ulils"
"ulladiesfootball"
"ullaughinsoc"
"ulrfc"
"ulriders"
"ulssc"
"ultennis"
"viking"
]
++ [
# remaining, most likely usernames
"_9thwonder"
"abc"
"activate"
"aiesec"
"air"
"aladdin"
"alaric"
"aldozzie"
"allenli"
"amg"
"amgl"
"annette"
"annlad"
"ards_backup"
"arisquez"
"arthur"
"austin"
"beta"
"bh"
"bigdave"
"bios"
"bizarroal"
"bmacaree"
"boardy"
"boddah"
"bogus.anime.fakh"
"bogus.bhudt.dacf"
"bogus.citoge.baym"
"bogus.electro.ba0a"
"bogus.fencing.baw5"
"bogus.harry.ba8f"
"bogus.hui.hong.baci"
"bogus.ironman.baqib"
"bogus.joe.bach"
"bogus.kenny.bas6"
"bogus.kerswin.baybb"
"bogus.kravmaga.ba0w"
"bogus.methi.baq5"
"bogus.nelsonmw.bauc"
"bogus.poshea.ba0m"
"bogus.redwolf.bawn"
"bogus.romanov.baat"
"bogus.ryan.bae-"
"bogus.rynnea.bask"
"bogus.sea.af"
"bogus.shane.c.ba8z"
"bogus.t1000.baggb"
"bogus.ullrugby.ba8p"
"brendan"
"bubba"
"c_material_removed"
"ca_worm"
"cactus"
"carticus"
"cathalc"
"cathald-broken"
"cdschedule"
"celtic"
"christine"
"cian"
"ciara"
"ciaran"
"colin"
"cosmo"
"counsel"
"creosote"
"crew"
"cues"
"cur"
"cwhelan"
"dac"
"daktulu"
"datacore"
"davec"
"daverus"
"deano"
"deccy"
"declanmu"
"deiji"
"dermotmc"
"derrick"
"deshocks"
"diarmuid"
"dippy"
"djraptor"
"dmackey"
"dmir"
"dom"
"dom_mckay"
"donie"
"donnacha"
"dos30"
"drazhar"
"duffman"
"eas"
"electal"
"emc"
"emilia"
"emma"
"emmag"
"ents"
"envcom"
"eoinh95"
"epgriffin"
"equest"
"fiacc"
"fint"
"flanno"
"fmannix"
"foodcoop"
"gamenet"
"ganainm"
"gar"
"ger88"
"ghama"
"ging"
"goborobo"
"gooner"
"greekweek"
"hawking"
"hb"
"homer"
"hoshi"
"ian"
"ianrice"
"ilug"
"infinity"
"ingenuus"
"internat"
"jamessy"
"jamiebarry"
"jbravo"
"jdonegan"
"joedredd"
"johann"
"jokill"
"jsoccer"
"jules"
"kate"
"katie"
"kellyj"
"kiely"
"koo"
"l_d_ablo"
"lakes"
"laura"
"lebowski"
"liabraid"
"lynn"
"mal"
"manuel"
"maraz"
"marieke"
"marky"
"mature"
"mbyrne"
"meanturtle"
"mickaful"
"mickasul"
"mikado"
"mikeh"
"mikkel"
"mixiezme"
"mmc"
"molly"
"moochie"
"moonser"
"mopic"
"mp"
"nastros"
"neutrino"
"new"
"nezzy"
"nkdc"
"nmcenroy"
"noelle"
"nugget"
"ob"
"omega"
"oneillbeano"
"pamela"
"peterj"
"photyl"
"plake"
"pmcg1986"
"pyro"
"qubeat"
"rachel"
"rachelg"
"ralmeida"
"raymond"
"razzlero"
"red"
"rmacm"
"rmorrissey"
"robson"
"selena"
"shark"
"shayscannell"
"shazlove"
"shelley"
"shelly"
"silver.old"
"sirhc"
"sithlord"
"sk"
"sligoer"
"slowey"
"smallp"
"smurfy"
"sordfish"
"soul98"
"soular"
"st"
"stefanovich"
"svp"
"szczerba"
"tangsoodo"
"tc"
"tenfor"
"teslacut"
"theematt"
"thomasl"
"tockman"
"ugm"
"vanzan"
"volleyb"
"warren"
"weather"
"wiles"
"yvonne"
"zrahman"
]
++ [
# former aliases
"david.dolphin"
"cc"
"mark.brennan"
];
};
};
}

29
dev.nix Normal file
View file

@ -0,0 +1,29 @@
# run with: nix-shell dev.nix
# has everything installed for dev
{ pkgs ? import <nixpkgs> {} }:
with pkgs;
let
imports =
let agenixCommit = "42d371d861a227149dc9a7e03350c9ab8b8ddd68";
in
{
agenix = import
(builtins.fetchTarball {
url = "https://github.com/ryantm/agenix/archive/${agenixCommit}.tar.gz";
sha256 = "14sszf5s85i4jd3lc8c167fbxvpj13da45wl1j7wpd20n0fic5c1";
})
{ inherit pkgs; };
};
in mkShell {
# nativeBuildInputs is usually what you want -- tools you need to run
nativeBuildInputs = [
pkgs.buildPackages.git
pkgs.buildPackages.colmena
pkgs.buildPackages.nmap
];
buildInputs = [ imports.agenix.agenix ];
shellHook = ''export EDITOR="${pkgs.nano}/bin/nano --nonewlines"'';
}

1274
flake.lock

File diff suppressed because it is too large Load diff

122
flake.nix
View file

@ -1,95 +1,33 @@
{
description = "Deployment for skynet";
inputs = {
# gonna start off with a fairly modern base
nixpkgs.url = "nixpkgs/nixos-unstable";
# Return to using unstable once the current master is merged in
# nixpkgs.url = "nixpkgs/nixos-unstable";
lix-module = {
url = "https://git.lix.systems/lix-project/nixos-module/archive/2.91.1-1.tar.gz";
inputs.nixpkgs.follows = "nixpkgs";
};
nixpkgs.url = "nixpkgs/nixos-23.05";
# utility stuff
flake-utils.url = "github:numtide/flake-utils";
agenix.url = "github:ryantm/agenix";
arion.url = "github:hercules-ci/arion";
alejandra = {
url = "github:kamadorueda/alejandra";
inputs.nixpkgs.follows = "nixpkgs";
};
colmena.url = "github:zhaofengli/colmena";
# we host our own
simple-nixos-mailserver = {
inputs.nixpkgs.follows = "nixpkgs";
url = "git+https://forgejo.skynet.ie/Skynet/misc_nixos-mailserver";
};
# email
# simple-nixos-mailserver.url = "gitlab:simple-nixos-mailserver/nixos-mailserver/nixos-23.05";
simple-nixos-mailserver.url = "gitlab:simple-nixos-mailserver/nixos-mailserver";
######################
### skynet backend ###
######################
skynet_ldap_backend.url = "git+https://forgejo.skynet.ie/Skynet/ldap_backend";
skynet_ldap_frontend.url = "git+https://forgejo.skynet.ie/Skynet/ldap_frontend";
skynet_website_wiki.url = "git+https://forgejo.skynet.ie/Skynet/wiki";
skynet_website_games.url = "git+https://forgejo.skynet.ie/Skynet/website_games";
skynet_discord_bot.url = "git+https://forgejo.skynet.ie/Skynet/discord-bot";
# for testing a local build
# skynet_discord_bot.url = "git+file:/_college/CompSoc/Skynet/discord_bot?shallow=1";
# sso.skynet.ie
skynet_ldap_backend.url = "gitlab:compsoc%2Fskynet%2Fldap/backend?host=gitlab.skynet.ie";
skynet_ldap_frontend.url = "gitlab:compsoc%2Fskynet%2Fldap/frontend?host=gitlab.skynet.ie";
#####################
### compsoc stuff ###
#####################
compsoc_public.url = "git+https://forgejo.skynet.ie/Computer_Society/presentations_compsoc";
#################
### skynet.ie ###
#################
# this should always point to teh current website
skynet_website.url = "git+https://forgejo.skynet.ie/Skynet/website_2017";
# these are past versions of teh website
skynet_website_2023.url = "git+https://forgejo.skynet.ie/Skynet/website_2017?rev=c4d61c753292bf73ed41b47b1607cfc92a82a191";
# this is not 100% right since this is from teh archive from 2022 or so
skynet_website_2017.url = "git+https://forgejo.skynet.ie/Skynet/website_2017?rev=edd922c5b13fa1f520e8e265a3d6e4e189852b99";
# this is more of 2012 than 2009 but started in 2009
skynet_website_2009.url = "git+https://forgejo.skynet.ie/Skynet/website_2009";
skynet_website.url = "gitlab:compsoc%2Fskynet%2Fwebsite/2023?host=gitlab.skynet.ie";
skynet_website_2016.url = "gitlab:compsoc%2Fskynet%2Fwebsite/2016?host=gitlab.skynet.ie";
};
nixConfig = {
bash-prompt-suffix = "[Skynet Dev] ";
extra-substituters = "https://nix-cache.skynet.ie/skynet-cache";
extra-trusted-public-keys = "skynet-cache:zMFLzcRZPhUpjXUy8SF8Cf7KGAZwo98SKrzeXvdWABo=";
};
outputs = {
self,
nixpkgs,
agenix,
alejandra,
colmena,
...
} @ inputs: let
pkgs = nixpkgs.legacyPackages.x86_64-linux.pkgs;
in {
formatter.x86_64-linux = alejandra.defaultPackage."x86_64-linux";
devShells.x86_64-linux.default = pkgs.mkShell {
name = "Skynet build env";
nativeBuildInputs = [
pkgs.buildPackages.git
colmena.defaultPackage."x86_64-linux"
pkgs.attic-client
pkgs.buildPackages.nmap
];
buildInputs = [agenix.packages.x86_64-linux.default];
shellHook = ''export EDITOR="${pkgs.nano}/bin/nano --nonewlines"; unset LD_LIBRARY_PATH;'';
};
outputs = { self, nixpkgs, ... } @inputs: {
# https://github.com/zhaofengli/colmena
# colmena apply --on agentjones
# colmena apply --on @dns
# nix flake lock --update-input skynet_ldap_backend
colmena = {
meta = {
nixpkgs = import nixpkgs {
@ -97,12 +35,12 @@
overlays = [];
};
specialArgs = {
inherit inputs self;
inherit inputs;
};
};
# installed for each machine
defaults = import ./machines/_base.nix;
defaults = import ./machines/_base.nix ;
# firewall machiene
agentjones = import ./machines/agentjones.nix;
@ -116,6 +54,9 @@
# icecast - ULFM
galatea = import ./machines/galatea.nix;
# Game host
optimus = import ./machines/optimus.nix;
# LDAP host
kitt = import ./machines/kitt.nix;
@ -131,29 +72,10 @@
# backup 1
neuromancer = import ./machines/neuromancer.nix;
# Skynet, user ssh access
# Skynet
skynet = import ./machines/skynet.nix;
# Main skynet sites
earth = import ./machines/earth.nix;
# Nextcloud
cadie = import ./machines/cadie.nix;
# trainee server
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

@ -1,139 +1,89 @@
{ pkgs, modulesPath, config, options, inputs, ... }:
{
pkgs,
modulesPath,
config,
options,
inputs,
lib,
...
}:
with lib; let
cfg = config.skynet;
in {
imports = [
# custom lxc mocule until the patch gets merged in
../applications/proxmox-lxc.nix
# (modulesPath + "/virtualisation/proxmox-lxc.nix")
(modulesPath + "/virtualisation/proxmox-lxc.nix")
# for the secrets
inputs.agenix.nixosModules.default
inputs.agenix.nixosModule
# base application config for all servers
../applications/_base.nix
# every sever may need the firewall config stuff
../applications/firewall.nix
#
inputs.lix-module.nixosModules.default
# 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 = {
lxc = mkOption {
type = types.bool;
# most of our servers are lxc so its true by default
default = true;
description = mdDoc "Is this a Linux Container?";
};
# flakes are essensial
nix.settings.experimental-features = [ "nix-command" "flakes" ];
system.stateVersion = "22.11";
services.openssh = {
enable = true;
settings.PermitRootLogin = "prohibit-password";
};
config = {
# if its a lxc enable
proxmoxLXC.enable = cfg.lxc;
users.users.root = {
initialHashedPassword = "";
nix = {
settings = {
# flakes are essensial
experimental-features = ["nix-command" "flakes"];
trusted-users = [
"root"
"@skynet-admins-linux"
];
};
openssh.authorizedKeys.keys = [
# no obligation to have name attached to keys
# https://nixos.wiki/wiki/Storage_optimization
# gc = {
# automatic = true;
# dates = "weekly";
# options = "--delete-older-than 30d";
# };
# Root account
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK6DjXTAxesXpQ65l659iAjzEb6VpRaWKSg4AXxifPw9 Skynet Admin"
# to free up to 10GiB whenever there is less than 1GiB left
extraOptions = ''
min-free = ${toString (1024 * 1024 * 1024)}
max-free = ${toString (1024 * 1024 * 1024 * 10)}
'';
};
# Brendan Golden
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEHNLroAjCVR9Tx382cqdxPZ5KY32r/yoQH1mgsYNqpm Silver_Laptop_WSL_Deb"
system.stateVersion = "22.11";
services.openssh = {
enable = true;
settings.PermitRootLogin = "prohibit-password";
};
users.users.root = {
initialHashedPassword = "";
openssh.authorizedKeys.keys = [
# no obligation to have name attached to keys
# Root account
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK6DjXTAxesXpQ65l659iAjzEb6VpRaWKSg4AXxifPw9 Skynet Admin"
# CI/CD key
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBDvexq/JjsMqL0G5P38klzoOkHs3IRyXYO1luEJuB5R colmena_key"
# Brendan Golden
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEHNLroAjCVR9Tx382cqdxPZ5KY32r/yoQH1mgsYNqpm Silver_Laptop_WSL_Deb"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKjaKI97NY7bki07kxAvo95196NXCaMvI1Dx7dMW05Q1 thenobrainer"
];
};
# skynet-admin-linux will always be added, individual servers can override the groups option
services.skynet.ldap_client.enable = true;
networking = {
# every sever needs to be accessable over ssh for admin use at least
firewall.allowedTCPPorts = [22];
# explisitly stating this is good
defaultGateway = {
address = "193.1.99.65";
interface = "eth0";
};
# cannot use our own it seems?
nameservers = [
# ns1
"193.1.99.120"
# ns2
"193.1.99.109"
];
};
# time on vendetta is strangely out of sync
networking.timeServers = options.networking.timeServers.default ++ ["ie.pool.ntp.org"];
services.ntp.enable = true;
# use teh above nameservers as the fallback dns
services.resolved.fallbackDns = config.networking.nameservers;
# 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;
environment.systemPackages = with pkgs; [
# for flakes
git
git-lfs
# useful tools
ncdu_2
htop
nano
nmap
bind
zip
traceroute
openldap
screen
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKjaKI97NY7bki07kxAvo95196NXCaMvI1Dx7dMW05Q1 thenobrainer"
];
};
# skynet-admin-linux will always be added, individual servers can override the groups option
services.skynet_ldap_client.enable = true;
networking = {
# every sever needs to be accessable over ssh for admin use at least
firewall.allowedTCPPorts = [22];
# explisitly stating this is good
defaultGateway = "193.1.99.65";
# cannot use our own it seems?
nameservers = [
# ns1
"193.1.99.120"
# ns2
"193.1.99.109"
];
};
# time on vendetta is strangely out of sync
networking.timeServers = options.networking.timeServers.default ++ [ "ie.pool.ntp.org" ];
services.ntp.enable = true;
# use teh above nameservers as the fallback dns
services.resolved.fallbackDns = config.networking.nameservers;
environment.systemPackages = [
# for flakes
pkgs.git
# useful tools
pkgs.ncdu_2
pkgs.htop
pkgs.nano
pkgs.nmap
pkgs.bind
pkgs.zip
pkgs.traceroute
pkgs.openldap
pkgs.screen
];
}

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

@ -1,60 +1,73 @@
/*
Name: https://matrix.fandom.com/wiki/Agent_Jones
Type: Physical
Hardware: PowerEdge r210
From: 2011 (?)
Role: Firewall
Notes: Used to have Agent Smith as a partner but it died (Ironically)
Name: https://matrix.fandom.com/wiki/Agent_Jones
Type: Physical
Hardware: PowerEdge r210
From: 2011 (?)
Role: Firewall
Notes: Used to have Agent Smith as a partner but it died (Ironically)
*/
{
pkgs,
lib,
nodes,
...
}: let
{ pkgs, lib, nodes, ... }:
let
# name of the server, sets teh hostname and record for it
name = "agentjones";
ip_pub = "193.1.99.72";
hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
};
name = "agentjones";
ip_pub = "193.1.99.72";
ip_priv = "193.1.99.125";
hostname = "${name}.skynet.ie";
in {
imports = [
./hardware/_base.nix
./hardware/RM001.nix
];
deployment = {
targetHost = hostname;
targetPort = 22;
targetUser = null;
targetUser = "root";
# somehow ssh from runner to this fails
tags = ["active-firewall"];
tags = [ "active" ];
};
services.skynet = {
host = host;
backup.enable = true;
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;
};
};
# 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;
}
];
networking.interfaces = {
eno2 = {
ipv4.addresses = [
{
address = ip_pub;
prefixLength = 26;
}
];
};
eno1 = {
#useDHCP = false;
ipv4.addresses = [
{
# internal address
address = ip_priv;
prefixLength = 26;
}
];
};
};
# this server is teh firewall
@ -73,25 +86,23 @@ in {
};
};
enable = false;
enable = true;
# gonna have to get all the
forward = builtins.concatLists (
# using this function "(key: value: value.config.skynet_firewall.forward)" turn the values ointo a list
lib.attrsets.mapAttrsToList (
key: value:
lib.attrsets.mapAttrsToList (key: value:
# make sure that anything running this firewall dosent count (recursion otherewise)
# firewall may want to open ports in itself but can deal with that later
if builtins.hasAttr "skynet_firewall" value.config
then
(
if value.config.skynet_firewall.enable
then []
else value.config.skynet_firewall.forward
)
else []
)
nodes
if builtins.hasAttr "skynet_firewall" value.config
then (
if value.config.skynet_firewall.enable
then []
else value.config.skynet_firewall.forward
)
else []
) nodes
);
};
}

View file

@ -1,47 +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

@ -1,47 +0,0 @@
/*
Name: https://en.wikipedia.org/wiki/List_of_Google_April_Fools%27_Day_jokes#CADIE
Why: CADIE is what google could have been, but they chickened out.
Type: VM
Hardware: -
From: 2023
Role: Google but better
Notes:
*/
{
pkgs,
lib,
nodes,
...
}: let
# name of the server, sets teh hostname and record for it
name = "cadie";
ip_pub = "193.1.99.77";
hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
};
in {
imports = [
../applications/nextcloud.nix
];
deployment = {
targetHost = hostname;
targetPort = 22;
targetUser = null;
tags = ["active"];
};
services.skynet = {
host = host;
backup.enable = true;
nextcloud.enable = true;
};
# this was causing a conflict for some reason
systemd.network.enable = lib.mkForce false;
}

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

@ -1,46 +0,0 @@
/*
Name: https://hitchhikers.fandom.com/wiki/Earth
Why: Our home(page)
Type: VM
Hardware: -
From: 2023
Role: Webserver
Notes:
*/
{
pkgs,
lib,
nodes,
inputs,
...
}: let
name = "earth";
ip_pub = "193.1.99.79";
hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
};
in {
imports = [
../applications/skynet.ie/skynet.ie.nix
../applications/skynet.ie/wiki.nix
];
deployment = {
targetHost = hostname;
targetPort = 22;
targetUser = null;
tags = ["active-core"];
};
services.skynet = {
host = host;
backup.enable = true;
website.enable = true;
wiki.enable = true;
};
}

View file

@ -1,29 +1,22 @@
/*
Name: https://en.wikipedia.org/wiki/Galatea_(mythology)
Why: Created as a product of artistic expression
Type: VM
Hardware: -
From: 2023
Role: Icecast server for ULFM
Notes:
Name: https://en.wikipedia.org/wiki/Galatea_(mythology)
Why: Created as a product of artistic expression
Type: VM
Hardware: -
From: 2023
Role: Icecast server for ULFM
Notes:
*/
{
pkgs,
lib,
nodes,
config,
...
}: let
{ pkgs, lib, nodes, config, ... }:
let
# name of the server, sets teh hostname and record for it
name = "galatea";
ip_pub = "193.1.99.111";
hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
};
name = "galatea";
ip_pub = "193.1.99.111";
ip_priv = "172.20.20.6";
hostname = "${name}.skynet.ie";
in {
imports = [
../applications/ulfm.nix
@ -32,14 +25,28 @@ in {
deployment = {
targetHost = hostname;
targetPort = 22;
targetUser = null;
targetUser = "root";
tags = ["active"];
tags = [ "active" ];
};
services.skynet = {
host = host;
backup.enable = true;
ulfm.enable = true;
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_ulfm = {
enable = true;
host = {
ip = ip_pub;
name = name;
};
};
}

View file

@ -1,28 +1,24 @@
/*
Name: https://zim.fandom.com/wiki/GIR
Why: Gir used to have this role before, servers never die
Type: VM
Hardware: -
From: 2023
Role: Email Server
Notes:
Name: https://zim.fandom.com/wiki/GIR
Why: Gir used to have this role before, servers never die
Type: VM
Hardware: -
From: 2023
Role: Email Server
Notes:
*/
{
pkgs,
lib,
nodes,
...
}: let
{ pkgs, lib, nodes, ... }:
let
# name of the server, sets teh hostname and record for it
name = "gir";
ip_pub = "193.1.99.76";
hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
};
name = "gir";
ip_pub = "193.1.99.76";
ip_priv = "172.20.20.5";
hostname = "${name}.skynet.ie";
#hostname = ip_pub;
in {
imports = [
../applications/email.nix
@ -31,14 +27,31 @@ in {
deployment = {
targetHost = hostname;
targetPort = 22;
targetUser = null;
targetUser = "root";
tags = ["active-core"];
tags = [ "active" ];
};
services.skynet = {
host = host;
backup.enable = true;
email.enable = true;
# add this server to dns
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;
};
};
# 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

@ -1,47 +1,56 @@
/*
Name: https://half-life.fandom.com/wiki/GLaDOS
Why: Glados has a vast experence of testing and deploying.
Type: VM
Hardware: -
From: 2023
Role: Git server
Notes: Each user has roughly 20gb os storage
20 * 100 = 2000gb
Name: https://half-life.fandom.com/wiki/GLaDOS
Why: Glados has a vast experence of testing and deploying.
Type: VM
Hardware: -
From: 2023
Role: Git server
Notes: Each user has roughly 20gb os storage
20 * 100 = 2000gb
*/
{
pkgs,
lib,
nodes,
...
}: let
{ pkgs, lib, nodes, ... }:
let
# name of the server, sets teh hostname and record for it
name = "glados";
ip_pub = "193.1.99.75";
hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
};
name = "glados";
ip_pub = "193.1.99.75";
ip_priv = "172.20.20.7";
hostname = "${name}.skynet.ie";
in {
imports = [
../applications/git/gitlab.nix
../applications/git/forgejo.nix
../applications/gitlab.nix
];
deployment = {
targetHost = hostname;
targetPort = 22;
targetUser = null;
targetUser = "root";
tags = ["active-git"];
tags = [ "active-gitlab" ];
};
services.skynet = {
host = host;
backup.enable = true;
gitlab.enable = true;
forgejo.enable = true;
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_gitlab = {
enable = true;
host = {
ip = ip_pub;
name = name;
};
};
}

View file

@ -1,40 +1,31 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:
{
config,
lib,
pkgs,
modulesPath,
...
}: {
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
./_base.nix
];
imports =
[ (modulesPath + "/installer/scan/not-detected.nix")
];
# Use the systemd-boot EFI boot loader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
boot.initrd.availableKernelModules = [ "ehci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" "sr_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
boot.initrd.availableKernelModules = ["ehci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" "sr_mod"];
boot.initrd.kernelModules = [];
boot.kernelModules = [];
boot.extraModulePackages = [];
fileSystems."/" =
{ device = "/dev/disk/by-uuid/9b177e4a-726e-4e68-a0e1-53837a8cae2e";
fsType = "ext4";
};
fileSystems."/" = {
device = "/dev/disk/by-uuid/f7b9d648-735f-44b7-b439-6af601b234a7";
fsType = "ext4";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/41AD-70AF";
fsType = "vfat";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/679E-C352";
fsType = "vfat";
};
swapDevices = [
{device = "/dev/disk/by-uuid/b1da9f57-1ed0-4f10-a6c0-6536a0017b2a";}
];
swapDevices =
[ { device = "/dev/disk/by-uuid/c5990c64-077f-45b1-96b5-44ec93e6651f"; }
];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
@ -43,6 +34,7 @@
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.eno1.useDHCP = lib.mkDefault true;
# networking.interfaces.eno2.useDHCP = lib.mkDefault true;
# networking.interfaces.enp0s29u1u1.useDHCP = lib.mkDefault true;
# networking.interfaces.enp1s0.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";

View file

@ -1,40 +1,31 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:
{
config,
lib,
pkgs,
modulesPath,
...
}: {
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
./_base.nix
];
imports =
[ (modulesPath + "/installer/scan/not-detected.nix")
];
# Use the systemd-boot EFI boot loader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
boot.initrd.availableKernelModules = [ "ehci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
boot.initrd.availableKernelModules = ["ehci_pci" "ahci" "usbhid" "usb_storage" "sd_mod"];
boot.initrd.kernelModules = [];
boot.kernelModules = [];
boot.extraModulePackages = [];
fileSystems."/" =
{ device = "/dev/disk/by-uuid/34918a4f-ca27-4070-a309-94bc59bdd743";
fsType = "ext4";
};
fileSystems."/" = {
device = "/dev/disk/by-uuid/5c1a39c9-c458-4518-b75b-5a831bebc204";
fsType = "ext4";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/8B03-4D11";
fsType = "vfat";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/8CBD-7032";
fsType = "vfat";
};
swapDevices = [
{device = "/dev/disk/by-uuid/515df5d9-abad-4068-bacc-559fb76e1fb1";}
];
swapDevices =
[ { device = "/dev/disk/by-uuid/c83e65ad-d252-4024-93a9-0253c5d8beac"; }
];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
@ -43,6 +34,7 @@
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.eno1.useDHCP = lib.mkDefault true;
# networking.interfaces.eno2.useDHCP = lib.mkDefault true;
# networking.interfaces.enp0s29u1u2.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;

View file

@ -1,33 +1,31 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:
{
config,
lib,
pkgs,
modulesPath,
...
}: {
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
./_base.nix
];
imports =
[ (modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = ["ehci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" "sr_mod"];
boot.initrd.kernelModules = [];
boot.kernelModules = [];
boot.extraModulePackages = [];
boot.initrd.availableKernelModules = [ "ehci_pci" "ahci" "usb_storage" "sd_mod" "sr_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
boot.loader.grub.device = "/dev/sda";
fileSystems."/" =
{ device = "/dev/disk/by-uuid/c48817e1-036f-49a7-adae-f63fc6c03cd5";
fsType = "ext4";
};
fileSystems."/" = {
device = "/dev/disk/by-uuid/a6c96ea1-1e66-4ad3-aef6-dd7131c83530";
fsType = "ext4";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/76CE-C65E";
fsType = "vfat";
};
swapDevices = [
{device = "/dev/disk/by-uuid/5408b486-62ce-45d9-bca5-b458e68ef7f4";}
];
swapDevices =
[ { device = "/dev/disk/by-uuid/eced30bd-b785-43e0-a202-cdaee7e0f4f7"; }
];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's

View file

@ -1,27 +1,17 @@
{
config,
options,
lib,
...
}:
with lib; let
{ config, options, lib, ... }: with lib;
let
# get a list of interfaces
interfaces = attrNames config.networking.interfaces;
# check if an IP has been assigned
has_ip = interface: (length config.networking.interfaces."${interface}".ipv4.addresses) != 0;
in {
config = {
skynet.lxc = false;
assertions = [
{
assertion = lists.any has_ip interfaces;
message = "Must have a ip address set";
}
{
assertion = config.networking.hostName != "nixos";
message = "Must have networking.hostName set";
}
];
};
}
}

View file

@ -1,58 +1,55 @@
/*
Name: https://en.wikipedia.org/wiki/KITT
Why: Kitt used to have this role before (as well as email and dns)
Type: VM
Hardware: -
From: 2023
Role: LDAP Server
Notes:
Name: https://en.wikipedia.org/wiki/KITT
Why: Kitt used to have this role before (as well as email and dns)
Type: VM
Hardware: -
From: 2023
Role: LDAP Server
Notes:
*/
{
config,
pkgs,
lib,
nodes,
...
}: let
{ pkgs, lib, nodes, ... }:
let
# name of the server, sets teh hostname and record for it
name = "kitt";
ip_pub = "193.1.99.74";
hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
};
name = "kitt";
ip_pub = "193.1.99.74";
ip_priv = "172.20.20.5";
hostname = "${name}.skynet.ie";
#hostname = ip_pub;
in {
imports = [
../applications/ldap/server.nix
../applications/ldap/backend.nix
../applications/discord.nix
../applications/bitwarden/vaultwarden.nix
../applications/bitwarden/bitwarden_sync.nix
../applications/ldap.nix
];
deployment = {
targetHost = hostname;
targetPort = 22;
targetUser = null;
targetUser = "root";
tags = ["active-core"];
tags = [ "active" ];
};
services.skynet = {
host = host;
backup.enable = true;
# add this server to dns
skynet_dns.records = [
{record=name; r_type="A"; value=ip_pub; server=true;}
{record=ip_pub; r_type="PTR"; value=hostname;}
];
# ldap setup
ldap.enable = true;
ldap_backend.enable = true;
services.skynet_backup = {
host = {
ip = ip_pub;
name = name;
};
};
# private member services
discord_bot.enable = true;
# committee/admin services
vaultwarden.enable = true;
services.skynet_ldap = {
enable = true;
host = {
ip = ip_pub;
name = name;
};
};
}

View file

@ -1,61 +0,0 @@
/*
Name: https://en.wikipedia.org/wiki/Marvin_the_Paranoid_Android
Why: Has terrible pain in all the diodes down its left side
Type: VM
Hardware: -
From: 2023
Role: For trainees.
Notes:
*/
{
pkgs,
lib,
nodes,
...
}: let
name = "marvin";
ip_pub = "193.1.99.81";
hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
};
groups = [
"skynet-admins-linux"
"skynet-trainees-linux"
];
groups_trusted = map (x: "@${x}") groups;
in {
imports = [
];
deployment = {
targetHost = hostname;
targetPort = 22;
targetUser = null;
# not deployed automatically as its a test server
tags = [];
};
# allow trainees to deploy
nix.settings.trusted-users =
[
"root"
]
++ groups_trusted;
# allow trainees access
services.skynet.ldap_client = {
groups = groups;
sudo_groups = groups;
};
services.skynet = {
host = host;
backup.enable = true;
};
}

View file

@ -1,56 +1,59 @@
/*
Name: https://williamgibson.fandom.com/wiki/Neuromancer_(AI)
Why: A sibling to Wintermute, stores and archives memories.
Type: VM
Hardware: -
From: 2023
Role: Backup Server
Notes:
Name: https://williamgibson.fandom.com/wiki/Neuromancer_(AI)
Why: A sibling to Wintermute, stores and archives memories.
Type: VM
Hardware: -
From: 2023
Role: Backup Server
Notes:
*/
{
pkgs,
lib,
nodes,
...
}: let
{ pkgs, lib, nodes, ... }:
let
# name of the server, sets teh hostname and record for it
name = "neuromancer";
ip_pub = "193.1.99.80";
hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
};
name = "neuromancer";
ip_pub = "193.1.99.80";
ip_priv = "172.20.20.7";
hostname = "${name}.skynet.ie";
in {
imports = [
./hardware/_base.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;
}
];
};
networking.interfaces.eno1.ipv4.addresses = [
{
address = ip_pub;
prefixLength = 26;
}
];
deployment = {
targetHost = hostname;
targetPort = 22;
targetUser = null;
targetUser = "root";
tags = ["active-core"];
tags = [ "active" ];
};
services.skynet = {
host = host;
backup.server.enable = true;
skynet_dns.records = [
{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

@ -1,47 +1,53 @@
/*
Name: https://en.wikipedia.org/wiki/Optimus_Prime
Why: Created to sell toys so this vm is for games
Type: VM
Hardware: -
From: 2023
Role: Game host
Notes:
Name: https://en.wikipedia.org/wiki/Optimus_Prime
Why: Created to sell toys so this vm is for games
Type: VM
Hardware: -
From: 2023
Role: Game host
Notes:
*/
{
pkgs,
lib,
nodes,
arion,
...
}: let
{ pkgs, lib, nodes, arion, ... }:
let
# name of the server, sets teh hostname and record for it
name = "optimus";
ip_pub = "193.1.99.90";
hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
};
name = "optimus";
ip_pub = "193.1.99.112";
ip_priv = "172.20.20.7";
hostname = "${name}.skynet.ie";
in {
imports = [
../applications/pelican/pelican.nix
../applications/games.nix
];
deployment = {
targetHost = hostname;
targetPort = 22;
targetUser = null;
targetUser = "root";
tags = ["active"];
tags = [ "active" ];
};
services.skynet = {
host = host;
backup.enable = true;
pelican = {
panel.enable = true;
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_games = {
enable = true;
host = {
ip = ip_pub;
name = name;
};
};
}

View file

@ -1,33 +1,35 @@
/*
Name: https://en.wikipedia.org/wiki/Ash_(Alien)
Why: Infilitrate into the network
Type: VM
Hardware: -
From: 2023
Role: Wireguard (VPN) Server
Notes: Thius vpn is for admin use only, to give access to all the servers via ssh
Name: https://en.wikipedia.org/wiki/Ash_(Alien)
Why: Infilitrate into the network
Type: VM
Hardware: -
From: 2023
Role: Wireguard (VPN) Server
Notes: Thius vpn is for admin use only, to give access to all the servers via ssh
*/
{
pkgs,
lib,
nodes,
...
}: let
{ pkgs, lib, nodes, ... }:
let
# name of the server, sets teh hostname and record for it
name = "ash";
ip_pub = "193.1.99.75";
ip_priv = "172.20.20.5";
name = "ash";
ip_pub = "193.1.99.75";
ip_priv = "172.20.20.5";
# hostname = "${name}.skynet.ie";
hostname = ip_pub;
hostname = ip_pub;
in {
imports = [
# applications for this particular server
../applications/firewall.nix
../applications/dns.nix
];
deployment = {
targetHost = hostname;
targetPort = 22;
targetUser = null;
targetUser = "root";
};
# these two are to be able to add the rules for firewall and dns
@ -36,7 +38,7 @@ in {
"ip daddr ${ip_pub} udp dport 51820 counter packets 0 bytes 0 accept"
];
services.skynet.dns.records = {
skynet_dns.records = {
external = [
"${name} A ${ip_pub}"
];
@ -46,6 +48,7 @@ in {
];
};
age.secrets.wireguard.file = ../secrets/wireguard.age;
networking = {
@ -71,12 +74,12 @@ in {
privateKeyFile = "/run/agenix/wireguard";
peers = [
{
# silver - Brendan
{ # silver - Brendan
publicKey = "46jMR/DzJ4rQCR8MBqLMwcyr2tsSII/xeCjihb6EQgQ=";
allowedIPs = ["172.20.21.2/32"];
allowedIPs = [ "172.20.21.2/32" ];
}
];
};
};
@ -84,4 +87,5 @@ in {
# needed to generate keys
pkgs.wireguard-tools
];
}

View file

@ -1,46 +1,75 @@
/*
Name: https://en.wikipedia.org/wiki/Skynet_(Terminator)
Why: Skynet is eternal
Type: VM
Hardware: -
From: 2023
Role: Webserver and member linux box
Notes: Does not host offical sites
Name: https://en.wikipedia.org/wiki/Skynet_(Terminator)
Why: Skynet is eternal
Type: VM
Hardware: -
From: 2023
Role: Webserver and member linux box
Notes:
*/
{
pkgs,
lib,
nodes,
inputs,
...
}: let
name = "skynet";
{ pkgs, lib, nodes, inputs, ... }:
let
# name of the server, sets teh hostname and record for it
name = "skynet";
# DMZ that ITD provided
ip_pub = "193.1.96.165";
hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
};
ip_pub = "193.1.96.165";
ip_priv = "193.1.99.79";
hostname = "${name}.skynet.ie";
hostname_int = "${name}.int.skynet.ie";
in {
imports = [
../applications/skynet_users.nix
../applications/skynet.ie.nix
];
deployment = {
targetHost = hostname;
targetHost = ip_priv;
targetPort = 22;
targetUser = null;
targetUser = "root";
# this one is manually deployed
tags = ["active-ext"];
tags = [ "active" ];
};
# it has two network devices so two
skynet_dns.records = [
#{record=name; r_type="A"; value=ip_pub; server=true;}
{record=name; r_type="A"; value=ip_priv; server=true;}
{record="${name}.int"; r_type="A"; value=ip_priv; server=true;}
{record=ip_priv; r_type="PTR"; value=hostname_int;}
];
services.skynet_backup = {
host = {
ip = ip_pub;
name = name;
};
};
# allow more than admins access
services.skynet_ldap_client = {
groups = [
"skynet-admins-linux"
"skynet-users-linux"
];
};
proxmoxLXC.manageNetwork = true;
networking.hostName = name;
networking.interfaces.eth0.ipv4.addresses = [
{
address = ip_priv;
prefixLength = 26;
}
];
services.skynet = {
host = host;
backup.enable = true;
website_users.enable = true;
host = {
ip = ip_priv;
name = name;
};
};
}
}

View file

@ -1,65 +1,71 @@
/*
Name: https://masseffect.fandom.com/wiki/Vendetta
Why: Vendetta held troves of important data waiting for folks to request it.
Type: Physical
Hardware: PowerEdge r210
From: 2011 (?)
Role: DNS Server
Notes: Using the server that used to be called Earth
Name: https://masseffect.fandom.com/wiki/Vendetta
Why: Vendetta held troves of important data waiting for folks to request it.
Type: Physical
Hardware: PowerEdge r210
From: 2011 (?)
Role: DNS Server
Notes: Using the server that used to be called Earth
*/
{
pkgs,
lib,
nodes,
...
}: let
{ pkgs, lib, nodes, ... }:
let
# name of the server, sets teh hostname and record for it
name = "vendetta";
ip_pub = "193.1.99.120";
hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
};
name = "vendetta";
ip_pub = "193.1.99.120";
ip_priv = "172.20.20.3";
hostname = "${name}.skynet.ie";
in {
imports = [
./hardware/_base.nix
./hardware/RM002.nix
];
networking.hostName = name;
deployment = {
targetHost = ip_pub;
targetPort = 22;
targetUser = null;
targetUser = "root";
tags = ["active-dns" "dns"];
tags = [ "active" "dns" ];
};
networking = {
# needs to have an address statically assigned
defaultGateway.interface = lib.mkForce "eno1";
interfaces.eno1.ipv4.addresses = [
{
address = "193.1.99.120";
prefixLength = 26;
}
];
};
services.skynet = {
host = host;
backup.enable = true;
dns = {
server = {
enable = true;
# primary dns server (ns1)
primary = true;
ip = ip_pub;
interfaces = {
eno1 = {
ipv4.addresses = [
{
address = "193.1.99.120";
prefixLength = 26;
}
];
};
};
};
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

@ -1,49 +1,56 @@
/*
Name: https://masseffect.fandom.com/wiki/Vigil
Why: Counterpart to Vendetta
Type: VM
Hardware: -
From: 2023
Role: DNS Server
Notes:
Name: https://masseffect.fandom.com/wiki/Vigil
Why: Counterpart to Vendetta
Type: VM
Hardware: -
From: 2023
Role: DNS Server
Notes:
*/
{
pkgs,
lib,
nodes,
...
}: let
name = "vigil";
ip_pub = "193.1.99.109";
hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
};
{ pkgs, lib, nodes, ... }:
let
name = "vigil";
ip_pub = "193.1.99.109";
ip_priv = "172.20.20.4";
hostname = "${name}.skynet.ie";
in {
imports = [
];
deployment = {
targetHost = ip_pub;
targetPort = 22;
targetUser = null;
targetUser = "root";
tags = ["active-dns" "dns"];
tags = [ "active" "dns" ];
};
services.skynet = {
host = host;
backup.enable = true;
dns = {
server = {
enable = true;
# secondary dns server (ns2)
primary = false;
ip = ip_pub;
};
services.skynet_backup = {
host = {
ip = ip_pub;
name = name;
};
};
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

@ -1,44 +1,52 @@
/*
Name: https://theportalwiki.com/wiki/Wheatley
Why: Whereever GLaDOS is Wheatly is not too far away
Type: VM
Hardware: -
From: 2023
Role: Gitlab Runner
Notes:
Name: https://theportalwiki.com/wiki/Wheatley
Why: Whereever GLaDOS is Wheatly is not too far away
Type: VM
Hardware: -
From: 2023
Role: Gitlab Runner
Notes:
*/
{
pkgs,
lib,
nodes,
...
}: let
{ pkgs, lib, nodes, ... }:
let
# name of the server, sets teh hostname and record for it
name = "wheatly";
ip_pub = "193.1.99.78";
hostname = "${name}.skynet.ie";
host = {
ip = ip_pub;
name = name;
hostname = hostname;
};
name = "wheatly";
ip_pub = "193.1.99.78";
ip_priv = "172.20.20.7";
hostname = "${name}.skynet.ie";
in {
imports = [
../applications/git/forgejo_runner.nix
../applications/gitlab_runner.nix
];
deployment = {
targetHost = hostname;
targetPort = 22;
targetUser = null;
targetUser = "root";
tags = ["active-git"];
tags = [ "active-gitlab" ];
};
services.skynet = {
host = host;
backup.enable = true;
forgejo_runner.enable = true;
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_gitlab_runner = {
enable = true;
runner.name = "runner01";
};
}

Binary file not shown.

View file

@ -1,20 +1,13 @@
age-encryption.org/v1
-> ssh-ed25519 V1pwNA mGy7a3SPHMxFaJ5S68jaRkPk16Ahxqp7C2YGnK6A4nM
TrEf7fz6yY7G2HXNxhnM4v7QkVrR5D6vdh+eUVbWbdQ
-> ssh-ed25519 4PzZog 5ixIvICVbbk2z8gqvodMAhCevBWdnfmpskWupnpMm04
r33h6oeu1jQQGs3mP15xtbRq50FGpKwtbbqWbSTQ1jE
-> ssh-ed25519 dA0vRg gUxwHHDBhxpYMxBE+UfTYJ4I8nY7cEdWG1XBSLLWtlY
pNawroXlES4EyNZSUUiEPNy+WNdG9AnHnUl+7qLB5Os
-> ssh-ed25519 5Nd93w AchMesYdEdLHtphyfCumqrdCRFABzNOEf7KfFgQWFAk
Xnier5jnPDl9n8F5r/R4CjBoEvmwAJRLQWnoWoAudec
-> ssh-ed25519 q8eJgg AgmUpmYT5z1qAFZ+uUY5a7huZ8Bhifs1ZuDBlg7ZJxU
kgaKF9t8cEKBc715dNocxA3o+2dwpK8erRo42NzeP9A
-> ssh-ed25519 KVr8rw AafFkG0axLsqGVs/k0DrzLFsKk4uXtqRbJIFhuAmj18
shiQFq5ZznBovnNXWfTNvSVX/O1X47hK6g13P8r6xN4
-> ssh-ed25519 fia1eQ AKbaMyAtdDHSpP5taXQQjaunzvO6yZuCOUjgV2+4iDc
yDFZ54QNklvVHUD1AkiaQ0sntqiRxkMGZw9yos/IvcI
-> ssh-ed25519 3pl/Kw KD86EfxdUwpfFW7wqf283Wmdw8o/qnVzXxTCrtNPsWI
L1a9WXktp4a9s1GxF6O7VV14ZPQOp/VqwS286Dqa3Tk
--- +jytGaOhLk0unuAlkbbtAFNde8Z+tKJ/3l3Y3tBgcFQ
€¡VV÷õÍ7 =ñOý]àbZêëj§p¸QKaXIúµNl¢_
ŠÐHsh3~<7E>ŒW/¿Ÿ<>ÝÌ ^áa\´¼Ô #/¤Ú‡i[÷Üfbó¶•áúXøØ
-> ssh-ed25519 V1pwNA 5icNZy9IB42T2Xnph6z0VGznaxiB0MHtC4yBUEOM534
avacsmljAR4DA0pdHq42o2YunyLweTjaX91QiuO7/0U
-> ssh-ed25519 rIwlvw r7IUmFs46NLNgITxj2hNMv2neldFI/OXlzpQOOZ/XD0
MkBLRr4uXWXW/xTo0EtkX2y5nbSwEfc6ChkaiIu8VoM
-> ssh-ed25519 q8eJgg jetnUDWCkX8P4fcvb3hA12TJolDKO2ZqcdmxUmx5myA
Ru2q2Y8+iIe7imaXeb9MTZyOoCv4P45SNgxGGxQlVRI
-> ssh-ed25519 mKj+iw wwsRXk+Wn3u+y+b/b3Fg6hSmJiV38tmYgRJqsStMnU0
avS7XgN/GYVi+2pjNTG+CZOLcKo+cPpCEPCVZV3DHF4
-> '$-grease y'
VGZ3E4+qHDVztqvY45Bo65M
--- u6b8TLW9fI2nKMvP1HCIRk8vIHWLrY3U1K8wse/s72s
üvÌTK&|lÿ4.àóo C§&ñ£0̤Úì¹ÀúIƈúûïöwÚ<77>^–„ sªÚ÷„H=<3D>­3Ã|E-C˜óøÌo×Ó×þCÂõ8Mç¸pø 6Ùk oM

Binary file not shown.

View file

@ -1,19 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 V1pwNA +Bzh++C1+jxdz1VwwhxPpO3XWn8fy7bsP2wX4mlQ63A
1GZxY76fwUOo/t/XeoCOEuxxq+oiU8+GDaasH7VTOkA
-> ssh-ed25519 4PzZog lkqPlBejVuYcBQwAZX96296VjJqyz3Q7J7O7OzfSDmw
x+bGIiw4SYhEePIkF5PLK6KK7EJ8Iay1oQIOJ18DtQY
-> ssh-ed25519 dA0vRg o0tqstSEhdxxdu4Bu8T/r8al3XJpIHvXp7xe8YNbJgo
m1OKX0L8Nn6ZrXI0Sk61fe8JIRbh+os7p0wzCMtdi6Y
-> ssh-ed25519 5Nd93w pYmPUfDB3HfJZDPgNh4Vmdu3UlTimrX4+EtUzSONyw4
C/URv/SZEtUlI2SBPNTfni4oI+bsYZ/Wq3xilcS6mMc
-> ssh-ed25519 q8eJgg k5Ml805g9vQ5Wv3hozSCAq8EGzvczTfpssrOeBlB+GE
IxRgNIg7Xi1RN9MthSqjsHoaLpsFWoUVd9f+ak9Qm08
-> ssh-ed25519 KVr8rw 5YvUQVmarpS4FgsFI8EFLz8tucmvs3V3Q8I0hT9q1i8
Lifm2EUWhv5hDU9mwkOu4fH8zyjEtGXW1qVBbC4dfvs
-> ssh-ed25519 fia1eQ sSzTT/AeSH5y4vyKt1Vl0bnkT11ZXINQi/pGU+M3oh0
Qm0ktboSsC0/+HBCIsOu2Oa+EAdT/DlStNLRpC+EOtw
-> ssh-ed25519 IzAMqA DhHry81R6JO3xWujL4l3uOmtqvdmk40srcWuXCU03kg
L4AWjbf1+bNXSMfBpC6DTKU1hvql+1mIRemeHZCFXos
--- Jlkn7bKGiezveI2e56iV/3B08/z/JxsJxgyvgZ6WhN0
·Ô|s<E28099> ÆX#Ï┘²?ÿWÔÊÆîÙº«Wñ(¡ßåˆ@†L [^tŒníÃhGc÷¢Šæ\¿><3E>¤­üå^D{*.! b

View file

@ -1,19 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 V1pwNA ud7vkafWPnZmwU0gvby16a/lB4VVkUhVpqnwvkMdKig
/PR7w91ONFOWIvObEKI+wD9XTxbjqQoMjlar9yqN8D0
-> ssh-ed25519 4PzZog nttwEm+xO2qLIkb+FqRmDeqbdidUune5CdS9AvHCmUs
raINPneffb9cQ6Zq3Jpwfz0MiIaTtoOI6s+1wB/S5t4
-> ssh-ed25519 dA0vRg uuSSiAgzEPgfh+VqE2QfB+8fkJlnUJsffF5/3C4Ovx0
1oFB/dDSQRpcETXb5IxYSqSG7oI8Y0i/myB6IaJqtUc
-> ssh-ed25519 5Nd93w ZZA2ylM3mB4xjxMzLmrYNujWTcjVsgKRzIYVsmPSqXI
30g14yh+pO4moRvnd9Xxe1/QQxmE2h2zHP9mqn8dULc
-> ssh-ed25519 q8eJgg lkPUz5/vn10nmk03AeA1W/6fp3tfyrdLq+kgoR5Cjy0
fHtjZtjYG18wWhhvZY3cn3FxxJiY41zQg16ltudBue8
-> ssh-ed25519 KVr8rw E2OijEik9tPfGCeRe+XDV+tKHTOOxojVbG0esTKuLCk
wXIOcUGlmF9GinF+Z81KQNiVACN2pthS1nwCK41IHMA
-> ssh-ed25519 fia1eQ VIfFJCbkM8ZvKKXN3+ZjxXIgK2y9vHpFdQopX25kUAk
utaTUdI2GBRxkDJT6qmxsdbGqjgSRP0ss4ZgQRQhQBM
-> ssh-ed25519 IzAMqA WX0QlrMPSMMvv3KnbOedpKcQrarKBQLHRXThmvveGmU
uz/jl2Ze8sdlCv5G6U1Dn5EiucQ1wlK4+/wwezX6jTI
--- fLAcK+fEa833GdqAvbD+sIr2ViSHQat1WQgPook94Ag
¬¬Á­°xçšáI¯ê¿i*ÿÂXÊ|ÔŸ‹*ž>€é!þK•GŸƒ£Ù7îoÍà)EU¡‰7ÛU<C39B>ˆ<EFBFBD>

View file

@ -1,26 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 V1pwNA 6NKUbOSUbwVjzW/ZUpl8qEiUTTegFlji4+tVJyqY3SE
fRQvaKnLMkVBboTEriQpWlGY9VBAP3ppsEbAB2QTScs
-> ssh-ed25519 4PzZog mp/+b5LpB+DvRduqAZiKWqkZq6+tlyQgVTZz7Oge2Us
OycqmZyDr3levWSfRFxypJOkITLDix0Q15Todya6BNc
-> ssh-ed25519 dA0vRg yp/4LvS9DbdatHFWFsP5qhH8CP8Bs0IjVSenUtG4+Xs
hHiJEtl1ffYXltsJzuEMLGUl2i/i3pFzv4bjbx/cbOI
-> ssh-ed25519 5Nd93w BTngmy4NGLGKhC8lPos63QEVBKoQT82KswQ22EypcQQ
OCnJMkOwwXQVbtCitUizXM4nynC6a1tiPSkm7MxulWA
-> ssh-ed25519 q8eJgg NaEjVcDBVICRgXuJchEdE4vg3qmkNmJAbDDxLq1fX0M
YFwUmEPwJIik5YJ2SV5IAmqGlY+h24voJJlrBaoCBwA
-> ssh-ed25519 KVr8rw ZnyVITZFkuozEs/rbTdxXDQNS3Nggo+JkBL1Icht2SM
B4jVVts5lK1kIlOWMl0eiN7TpsTeJZWIu7NqildxeGE
-> ssh-ed25519 fia1eQ kvzARRScl/eypC2a5cY66sXcH+TZqz4sYg4W/k9iJxQ
Ga+4TVvXiQ6i5/+fgUQ3E5tJiLqdBsEsXjenXEpRV/A
-> ssh-ed25519 IzAMqA 5sizvlhLhAhAR1bViHJtRJ8fAIO56TAuLVSOwE177QE
b9oJ8BC2xiBjvc3D0H0EF7bSNDlpvIidyBCTf04ndJI
-> ssh-ed25519 uZzB3g g9y66zNmQbqP6Rbhg2t06W3YOgy8DkRvJZbWVegT71s
2dH7E76tDMrWQJbLPefyORP66iaPHQnSjwu8NCdSyJo
-> ssh-ed25519 Hb0ipQ azOzBLXfshInlFVpV0PzIBidL/VzA/+kKRXFFVD6ZF4
iXBF/Wcv4KWo5qUXUlyimuo0l6aClKxOCtkm3MxAIBc
-> ssh-ed25519 IzAMqA EWitYyV8RsPIB6HEFE2OI/C1zcC6WfBEeDI62rGVmkk
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,51 +1,27 @@
age-encryption.org/v1
-> ssh-ed25519 V1pwNA nMGYHPjBRQ+8FE2j3JLTb2gfqxFvEDSF5XKvVYILgS4
xoFB5NeaXLMQhM9ELoooDNNnrjJWFCA+f45Y+YtAOBs
-> ssh-ed25519 4PzZog zuhv6HbfpcIlcueD6SyHD7hRcrPnvMDy1hvXcXTLEBY
VI6ZX5745Tsv1AMvjPKrHWEI2YO4rCVtAMDWLQrzsFs
-> ssh-ed25519 dA0vRg U1zhPjiM0ANz4i9iRSaX9ut/kACtrH/uk4VYk/Cmtx4
DryI/XiQeggMAIBu4Qb9P7Od4cnQUNFFuim2OKwib5M
-> ssh-ed25519 5Nd93w VICIqg3swkEAagNzDppCX2/lDMh5D/pYqi8wjL9ilH8
DLcvw4k9r1RDrueCD/vqX1iEL55hxld3eJr5MCS7YNE
-> ssh-ed25519 q8eJgg DyH3qYX/PfoltL0P2lBzP4wwH/VmYusidfD7MaS1PBQ
ilj+oIaQwj6jSsDNagpLTJXZywWB2IeLUa6pKlcEvIw
-> ssh-ed25519 KVr8rw +JGGMHN2zMPN4leJIZkBTOrhzb8BYQKMbSrAuIpCU2k
Sa2V0qsQbKPLvuVewBjTdIgv1acTYIN+CMIlB+ExIok
-> ssh-ed25519 fia1eQ jG4Lr4j3f0QNucooo80HUJAOnLiTAg8mxzYRDnjXrFQ
C+cZWCaRemvsiCMJ7wn/6g/12ABvKEaYIaU6b3Fpo8g
-> ssh-ed25519 /Gb5gQ QO7t0R8SjnfqZZ6upxKXALytoi6OFZZ4mFpS7XgnlDQ
+yQd4GdflWOzRutCAplDqvee+0dCNdd/ScT8QZyioNQ
-> ssh-ed25519 NtlN/A Y56En/7BcL9IIzBWbOfPzuAah/nPFANXxu3iN6+q8XM
gqw6EsuuDx49aTb6DWtI1ZACDAGL1VnsKB6LAOH6F0U
-> ssh-ed25519 v2Y09A 9MgpxeQcQDGvHkEyb0+f0vRZfyXE7EUUcBXCyw8w7mk
sdM/6DwpC5kv8yg39edGpm6YV3VzkFLRkIleiwhOKew
-> ssh-ed25519 XSrA6w tp83J4GXjFjQFq14M+Z+PDCmO4ZjJ1qufdQEO6GHzkk
KVri/HL0E/byrA0C3iM8+AMsR0x46pdMrRKipvliSzw
-> ssh-ed25519 MhHMYA Pwi4Tq4iJv8/ylaI4VAEzcGAPPfl+T2S/oUp3JsPTVo
8Q0DSQMe9gunPGxYv6M4ilBapKfNx7qacddEc39lgNY
-> ssh-ed25519 3erWHw vo6DeH1ub4VcT3dnvPYZC95MHxaABkZ4MW8NRxqOBUw
6yHGAoHq/u9pSi06jWCkcN230ntCkYADsCB//ISO+0Q
-> ssh-ed25519 uZzB3g FbeDwGg3Se/SVIVVAhgtRAO9wZM72M4ulGcXKBtw51k
+T7O+KNr/QXoGUG8uULBYgDXRWhrwv4ZImjWp8ltxRk
-> ssh-ed25519 CqOTGQ yG/8YtD4tRo8X5Q4kDyIr0xT5JwBg/Wk9NrkJMMCqgI
ZszCJYQGN1eRnRJ9KLpLrxy7j45bL5CtRTfLt4KwRt4
-> ssh-ed25519 IzAMqA 9AIaFKdsA4yqORM9NNlFkp4TI2q14uy1dtUUP31a6A8
9FwzT1ZQABt3om9OTodEKgxxgVU9H+VlV8X9AucxndY
-> ssh-ed25519 Hb0ipQ 2jhZm+mZoKzeBRjt0q5+T2HX+VM/H2Zy/7SyXuTeGxY
J6ds5gRKFv754f7NrbGGCXKLTcad8YGVrM0ndDHlFZ8
-> ssh-ed25519 3pl/Kw IrzcYOatmG1O2I0CbNz2Phs32G3nz5Jv9Uizj4cqhAE
YDFNtbNUVpAQXyWIZssNANKEc4LoG4cEdmKBRWMFdas
-> ssh-ed25519 SqDBmA erRarQNCMp2QrQBAThQ23RoTAK0Uzz9//SqgBdldFDI
bi/LlSWcaPDHc7lxXuzMJUf6tAlv/6oF/go6NcQEcmA
-> ssh-ed25519 UE6fcQ QjWmHf2lgJ5QctSg9WlvLRueeE1N9WQdV1ZRrDIGsWA
K2IdKT9WpS6bsONh44h28i3Vm64YxhJFDas+rFPRbs0
-> ssh-ed25519 YFaxCg wUWp3BvPpjSKKySmCb3gsO06P+F6GiYJU/wwfTAqTU4
1D1+FEXxZES4cVbl/tSaMfiVk5yJlb9y9RsThyaK13A
-> ssh-ed25519 elCEeg jyijilsUuQ14LYrZPzE6CAMxgVmGFaxR2EbIP48l5Cw
kdEeI5a8gfh5d1mVbiMWOgGP9qmxc01EEifN00l51yM
-> ssh-ed25519 8vZ9CQ k55pfEEYf/3sC7M9YyA0zlQdv69N324fvNgW7/0/hxQ
EPJ0Bv///iKOz0y1dVT/jGTobSYjKGW8+Os1lLBMDtc
-> ssh-ed25519 rmrvjw kqTB4IBJ/wr6P2g21TmbqdNQB5XDxCSU9lwVRAPiZhM
3d9tjv3l3ws74DW+LeHVYUDViJWg+zv93mFv1C3mS2c
--- cUHw7QjEwLsUCL+1WhhNByWzfOIFrRmA/4JPbYgukCE
é *8ÿ¶QÙËš=R™=Å<>yg¯<67>u Œü"¸eSI<53>\ÑË[šŒ¤ŠÏG3.UzÜ Ã»4±—½ïEÊŒýÀ ß\»ý) eðï¼X}H°f§¬X1 ç“Sá¸Ç){¹x+Úcø1ãùù3mc³k?œ ïh:ý„bô2“¤¾gB@Ï<>-á'âÄÿ°åÎF/Žœ #ÿŠÆH+Ô¼s¸•<øå™êÞîþK†ìCÁÁšQ˧ie;¥Â-kžˆRx= (#}i¢<69>à<EFBFBD>°nße
-> ssh-ed25519 V1pwNA 8GOIUD9Kw0Rgk9f0y4X/DAU1CJkIElC+ncXKTZqiI0M
fUaEgN+etR6cCO9RZYlS39sIL+3HoN4vbrNx3frV2MQ
-> ssh-ed25519 rIwlvw oRJq+SnMgO14Vn9mas+cA7PxRsCTCH7nN1R1UnteXGQ
id5gxG2xpSMFRtv0fuW/4gqYzNVWMnUnZQrHywO0cSo
-> ssh-ed25519 q8eJgg 3YWRSNOeGqbxfZ5j41DHCjnnH1o7KLZpOZmPgiDTmBE
HFL0tvUPf7ZPgH2e4KOXjQIhDsfU5h1Y/SjCGvnSvU8
-> ssh-ed25519 XSrA6w y8Gqm8ATfOiWaafVP4a0Ah+KwXZFa767gw79UpFvyFo
fGmxf6g/VN/A+fzy+eSkk+H+0nBRPwot1Vev5AU+Otc
-> ssh-ed25519 DVzSig 9oSFqSbP8NIve7/Li5MO0qoXY/j0mz1LoIi22nzNTmU
btg877VtFr/q6rq7KXVRoCIrZig4qYR8CaUCBKEhfWQ
-> ssh-ed25519 SqDBmA PdB0Fa4Lv4tQn2Cw9ClOHRrCNR3igGsSVdMnunDmGBs
7dW8yReE/Ti/9x6OE9xfP5jkm2QLV66lm/kG91AqE0k
-> ssh-ed25519 IzAMqA yLOTmqlrQ5VB6gCIjfvkCbuejVDRWCGPsJklZExfdnM
5E4F45VkETQqQWT9cJx4Owl9QxqbfliU4JtV6gj9C3s
-> ssh-ed25519 uZzB3g F0KPMYgCSJMgbh4DBewNHsfT8HtpF/eaces8AV/quF0
32i2UGD2jRrba5oz9jO2P8uSstTi+FrdTreJh0wyv8c
-> ssh-ed25519 Hb0ipQ MhOrRdOrE3HF1wlvea6jgcF2H+EvFy0VpwP2UcfA32k
JpOvrHJaqP75uzEGuhbuAYrhaQ3mtoZmz1wf5KpfI0Q
-> ssh-ed25519 uZzB3g 2Hv1za/ZTu/pL4F6ER0Q7nOEjfbbtTEyUM5wm/L0lCk
Fl7UfjUzkPEngUIq700EENUHdsU1cZBwGQVuaBOzl6M
-> qY.@U-grease J
zK/SyCeVwFefcB2JLa2au8egE7eHU8oEKKY54WUYfx3oSQqYdZdMTxMjY+97+lYj
yjGCjir8pM4IQWDC
--- xxKgKXQD88mrgIvmzV50SZw3xDKwEvRkQdaW14FdWOM
(V”xí<C3AD>§†þ¿pj<08>Ý͆Fj0¢\'¹,Aæíößaë(ùâON€_<16>†e5Ì¿Tq<>§\JªÙGTÀò¦³ãâNá>»dDÝ¢-Ì®t0Öü$—Xò³×ê¢ywØÕnü¶S„•¬¹Y§ù¬:Ôƒ‚>‰î<`·¨‘zÎ(¶äW#†ùo÷a»Yú M(oÅ<¥Ή¿\®M¬|Vœp¥·Â'zÒçXê÷
ý54f³þ©·Òò=Í¢D]M .L$í“<cD@

Binary file not shown.

View file

@ -1,25 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 V1pwNA rR7/KSP2skc5HZDN98g30IIXuNDJsghQWfyVF57glW0
oSpYnVqLObrE/MQNHonzOmpGk/BcDyMxwPPQauUB8Zo
-> ssh-ed25519 4PzZog bUKm5Fqx40JQ/8BdJvP15xQvIjwTAxuAqsoPIAyRDi0
xGvp4hTdaiqD7cxjJTjmJHgehY8VCOVqvvXNIQoGrRU
-> ssh-ed25519 dA0vRg Ty2EEwt35A8ZigOkVmYlLgXbMePI3WALtM1McsFtQnQ
ygu01cCNYlaW9e0APNrDGPjfJE1KkNq1nqi5d6fwqm8
-> ssh-ed25519 5Nd93w UwOXbO00n1/2pxpz98BZ7yIaEr1PXEvOg7F3Nl80yTY
+E2VbVQXngXUHUQlc2P6ebU0/anioRu/EZgpdf/N8/Q
-> ssh-ed25519 q8eJgg 82IpLMlE/9Wp4fD8PHIiKsff9jJYJtoPF58xCnb6GAU
Ip27egoy6jMgvvTRg6q5NXeTlv9EFhK9PM8rCFu8LhU
-> ssh-ed25519 KVr8rw xEE59aHcuIIB/5pbH3bZuZQ7W2CDUCoyT6EmdOWiZ2s
2uaA7Nx8DNbmGvY/ns/DRHZ1zTZ+JifkR4eVtSzCRd8
-> ssh-ed25519 fia1eQ /YtGDHVjZTzDO7baOphkGvY0zCgElNT9UMpMhhjFCEw
03+ungOpBCqgTj/kyH1hz1LWTHSlkZ6Qb0c4i9bwOZ0
-> ssh-ed25519 IzAMqA kSa3Kbz9SyIe1pXTBi39RxVMi6QQV0rjAPgdbEmmJRA
SO7M5B6LR1aZ8r7mFjFAF+Zl1tlsq3j/3/BVkSPWFcE
-> ssh-ed25519 uZzB3g 1WjjfJ50NZO2C7qKp4WOtDHEUlkF0CFmiehMsY8/6Wk
TP6FwDJp0nKd+FaB0tnZa9XoD8tQponT8wK2xZ/k/A4
-> ssh-ed25519 Hb0ipQ vRwS9w7tO0yryHoip+sqbsD67lqXLD+6hJDNi9YClAU
NiIy//77gNuQ9UJgvt1UPqD99QJzfbh4WFld7Ln0GtE
-> ssh-ed25519 IzAMqA J5spaIE4OAKJsvd1hOy3M2cCbmAG0/9l0dsnKlZfxi4
RT95kFe4vKr0HQVz+6Gfm7pat7HvSahle2zMhEaQ8DM
--- ag6/92VREDBr8oQUKcFbj25qK4gcMdHa+ej3hf+igbc
År:ºûÛÓfÆ)sºûß;˲fI[±g<'­òª3rûÃrœõÅk×™‡âÝB™º+c‡WÌç|÷䘨~ŒË”7ÓãªãϵU<C2B5> ECò ýʺžq!jÉ7¬Å1VŽ¥Î®<>SØ4ÿG8i9:™ßíHl9VµDmnvS¹Š

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