Compare commits
No commits in common. "d0fc6af26526562338ec2f25c134a47026be6a1a" and "590f42d5d96e838b008423937cb09c80bf30318c" have entirely different histories.
d0fc6af265
...
590f42d5d9
15 changed files with 154 additions and 618 deletions
43
.sops.yaml
43
.sops.yaml
|
|
@ -1,11 +1,38 @@
|
||||||
|
# SOPS configuration for StuRa HTW Dresden infrastructure
|
||||||
|
#
|
||||||
|
# This file defines which keys can decrypt which secrets.
|
||||||
|
# Add GPG public keys (.asc files) or age keys to keys/hosts/ and keys/users/
|
||||||
|
# to grant decryption access to hosts and users respectively.
|
||||||
|
|
||||||
keys:
|
keys:
|
||||||
- &goeranh age16m8vvvpw4azfy6gygtstyyj6nd2sf848f7f7argaghwhct38muxsgxpeek
|
# Admin/user keys - add GPG public keys here
|
||||||
- &gradient age1kfxhahmxprheer63shv68slpmk5qz29nyx3kp4q6n879zz9ha34q04n50x
|
# Example:
|
||||||
|
# - &user_admin_key age1... or pgp fingerprint
|
||||||
|
|
||||||
|
# Host keys - add host-specific keys here
|
||||||
|
# Example:
|
||||||
|
# - &host_proxy_key age1... or pgp fingerprint
|
||||||
|
# - &host_git_key age1... or pgp fingerprint
|
||||||
|
|
||||||
|
# Define which keys can access which files
|
||||||
|
creation_rules:
|
||||||
|
# Default rule: all secrets can be decrypted by admin keys
|
||||||
|
- path_regex: secrets/.*\.yaml$
|
||||||
|
# key_groups:
|
||||||
|
# - pgp:
|
||||||
|
# - *user_admin_key
|
||||||
|
# - age:
|
||||||
|
# - *user_admin_key
|
||||||
|
|
||||||
# Host-specific secrets (example)
|
# Host-specific secrets (example)
|
||||||
creation_rules:
|
# - path_regex: secrets/proxy/.*\.yaml$
|
||||||
- path_regex: hosts/gradient/secrets.sops.yaml$
|
# key_groups:
|
||||||
key_groups:
|
# - pgp:
|
||||||
- age:
|
# - *user_admin_key
|
||||||
- *gradient
|
# - *host_proxy_key
|
||||||
- *goeranh
|
|
||||||
|
# - path_regex: secrets/git/.*\.yaml$
|
||||||
|
# key_groups:
|
||||||
|
# - pgp:
|
||||||
|
# - *user_admin_key
|
||||||
|
# - *host_git_key
|
||||||
|
|
|
||||||
|
|
@ -37,16 +37,9 @@ in
|
||||||
experimental-features = [
|
experimental-features = [
|
||||||
"nix-command"
|
"nix-command"
|
||||||
"flakes"
|
"flakes"
|
||||||
"blake3-hashes"
|
|
||||||
];
|
];
|
||||||
# trusted-users = [ "administration" ];
|
# trusted-users = [ "administration" ];
|
||||||
auto-optimise-store = true;
|
auto-optimise-store = true;
|
||||||
trusted-substituters = [
|
|
||||||
"https://gradient.adm.htw.stura-dresden.de/cache/stura"
|
|
||||||
];
|
|
||||||
trusted-public-keys = [
|
|
||||||
"gradient.adm.htw.stura-dresden.de-stura:rVy7JDos8CTvKJsrotP2/y/ICbCNv69HKy0Dfsgrafs="
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
optimise.automatic = true;
|
optimise.automatic = true;
|
||||||
gc = {
|
gc = {
|
||||||
|
|
|
||||||
114
flake.lock
generated
114
flake.lock
generated
|
|
@ -8,9 +8,7 @@
|
||||||
"flake-parts": "flake-parts",
|
"flake-parts": "flake-parts",
|
||||||
"flake-utils": "flake-utils",
|
"flake-utils": "flake-utils",
|
||||||
"napalm": "napalm",
|
"napalm": "napalm",
|
||||||
"nixpkgs": [
|
"nixpkgs": "nixpkgs",
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"pyproject-build-systems": "pyproject-build-systems",
|
"pyproject-build-systems": "pyproject-build-systems",
|
||||||
"pyproject-nix": "pyproject-nix",
|
"pyproject-nix": "pyproject-nix",
|
||||||
"systems": "systems",
|
"systems": "systems",
|
||||||
|
|
@ -79,21 +77,6 @@
|
||||||
"type": "gitlab"
|
"type": "gitlab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"crane": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1777335812,
|
|
||||||
"narHash": "sha256-bEg5xoAxAwsyfnGhkEX7RJViTIBIYPd8ISg4O1c0HFc=",
|
|
||||||
"owner": "ipetkov",
|
|
||||||
"repo": "crane",
|
|
||||||
"rev": "5e0fb2f64edff2822249f21293b8304dedaaf676",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "ipetkov",
|
|
||||||
"repo": "crane",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"disko": {
|
"disko": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
|
|
@ -185,24 +168,6 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-utils_2": {
|
|
||||||
"inputs": {
|
|
||||||
"systems": "systems_2"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1731533236,
|
|
||||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"git-hooks": {
|
"git-hooks": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-compat": [
|
"flake-compat": [
|
||||||
|
|
@ -251,34 +216,12 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"gradient": {
|
|
||||||
"inputs": {
|
|
||||||
"crane": "crane",
|
|
||||||
"flake-utils": "flake-utils_2",
|
|
||||||
"nixpkgs": "nixpkgs"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1777807825,
|
|
||||||
"narHash": "sha256-LIHC5ayGLbEXY7wBrd71EE12xZDBltYqeE4qdEvWbC0=",
|
|
||||||
"owner": "wavelens",
|
|
||||||
"repo": "gradient",
|
|
||||||
"rev": "0f5779845044d2a39e5f599f781d6cfb9248a219",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "wavelens",
|
|
||||||
"repo": "gradient",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"mailserver": {
|
"mailserver": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"blobs": "blobs",
|
"blobs": "blobs",
|
||||||
"flake-compat": "flake-compat_2",
|
"flake-compat": "flake-compat_2",
|
||||||
"git-hooks": "git-hooks",
|
"git-hooks": "git-hooks",
|
||||||
"nixpkgs": [
|
"nixpkgs": "nixpkgs_2"
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1773912645,
|
"lastModified": 1773912645,
|
||||||
|
|
@ -323,11 +266,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1777268161,
|
"lastModified": 1771848320,
|
||||||
"narHash": "sha256-bxrdOn8SCOv8tN4JbTF/TXq7kjo9ag4M+C8yzzIRYbE=",
|
"narHash": "sha256-0MAd+0mun3K/Ns8JATeHT1sX28faLII5hVLq0L3BdZU=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "1c3fe55ad329cbcb28471bb30f05c9827f724c76",
|
"rev": "2fc6539b481e1d2569f25f8799236694180c0993",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -352,29 +295,29 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs-unstable": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1777268161,
|
"lastModified": 1773831496,
|
||||||
"narHash": "sha256-bxrdOn8SCOv8tN4JbTF/TXq7kjo9ag4M+C8yzzIRYbE=",
|
"narHash": "sha256-JW2/QPyCVzmouqEp1H9kNa8JXd7xEhlam9sy3TYfhDY=",
|
||||||
"owner": "nixos",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "1c3fe55ad329cbcb28471bb30f05c9827f724c76",
|
"rev": "826430a188181a750ffa5948daff334039c5d741",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "nixos",
|
"owner": "NixOS",
|
||||||
"ref": "nixos-unstable",
|
"ref": "nixos-25.11-small",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_3": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1777077449,
|
"lastModified": 1776734388,
|
||||||
"narHash": "sha256-AIiMJiqvGrN4HyLEbKAoCSRRYn0rnlW5VbKNIMIYqm4=",
|
"narHash": "sha256-vl3dkhlE5gzsItuHoEMVe+DlonsK+0836LIRDnm6MXQ=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "a4bf06618f0b5ee50f14ed8f0da77d34ecc19160",
|
"rev": "10e7ad5bbcb421fe07e3a4ad53a634b0cd57ffac",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -438,10 +381,8 @@
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"authentik": "authentik",
|
"authentik": "authentik",
|
||||||
"disko": "disko",
|
"disko": "disko",
|
||||||
"gradient": "gradient",
|
|
||||||
"mailserver": "mailserver",
|
"mailserver": "mailserver",
|
||||||
"nixpkgs": "nixpkgs_2",
|
"nixpkgs": "nixpkgs_3",
|
||||||
"nixpkgs-unstable": "nixpkgs-unstable",
|
|
||||||
"sops": "sops"
|
"sops": "sops"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -452,11 +393,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1777338324,
|
"lastModified": 1776771786,
|
||||||
"narHash": "sha256-bc+ZZCmOTNq86/svGnw0tVpH7vJaLYvGLLKFYP08Q8E=",
|
"narHash": "sha256-DRFGPfFV6hbrfO9a1PH1FkCi7qR5FgjSqsQGGvk1rdI=",
|
||||||
"owner": "Mic92",
|
"owner": "Mic92",
|
||||||
"repo": "sops-nix",
|
"repo": "sops-nix",
|
||||||
"rev": "8eaee5c45428b28b8c47a83e4c09dccec5f279b5",
|
"rev": "bef289e2248991f7afeb95965c82fbcd8ff72598",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -480,21 +421,6 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"systems_2": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681028828,
|
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"uv2nix": {
|
"uv2nix": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
|
|
|
||||||
25
flake.nix
25
flake.nix
|
|
@ -4,14 +4,11 @@
|
||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11";
|
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11";
|
||||||
nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable";
|
|
||||||
authentik = {
|
authentik = {
|
||||||
url = "github:nix-community/authentik-nix";
|
url = "github:nix-community/authentik-nix";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
};
|
};
|
||||||
mailserver = {
|
mailserver = {
|
||||||
url = "git+https://gitlab.com/simple-nixos-mailserver/nixos-mailserver?ref=nixos-25.11";
|
url = "git+https://gitlab.com/simple-nixos-mailserver/nixos-mailserver?ref=nixos-25.11";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
};
|
};
|
||||||
sops = {
|
sops = {
|
||||||
url = "github:Mic92/sops-nix";
|
url = "github:Mic92/sops-nix";
|
||||||
|
|
@ -21,22 +18,17 @@
|
||||||
url = "github:nix-community/disko";
|
url = "github:nix-community/disko";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
gradient = {
|
|
||||||
url = "github:wavelens/gradient";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs =
|
outputs =
|
||||||
{
|
{
|
||||||
self,
|
self,
|
||||||
nixpkgs,
|
nixpkgs,
|
||||||
nixpkgs-unstable,
|
|
||||||
authentik,
|
authentik,
|
||||||
mailserver,
|
mailserver,
|
||||||
disko,
|
disko,
|
||||||
sops,
|
sops,
|
||||||
gradient
|
}:
|
||||||
}@inputs:
|
|
||||||
let
|
let
|
||||||
sshkeys = [
|
sshkeys = [
|
||||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINABEf0jBjtDdezDDtvl1v27l0DbHP2XUgMARTZXC+MR goeranh@node5"
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINABEf0jBjtDdezDDtvl1v27l0DbHP2XUgMARTZXC+MR goeranh@node5"
|
||||||
|
|
@ -52,6 +44,15 @@
|
||||||
pkgs = nixpkgs.legacyPackages.x86_64-linux;
|
pkgs = nixpkgs.legacyPackages.x86_64-linux;
|
||||||
in
|
in
|
||||||
pkgs.mkShell {
|
pkgs.mkShell {
|
||||||
|
# Import GPG keys from keys directory
|
||||||
|
sopsPGPKeyDirs = [
|
||||||
|
"${toString ./.}/keys/hosts"
|
||||||
|
"${toString ./.}/keys/users"
|
||||||
|
];
|
||||||
|
|
||||||
|
# Isolate sops GPG keys to .git/gnupg (optional)
|
||||||
|
# sopsCreateGPGHome = true;
|
||||||
|
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
sops.packages.x86_64-linux.sops-import-keys-hook
|
sops.packages.x86_64-linux.sops-import-keys-hook
|
||||||
];
|
];
|
||||||
|
|
@ -183,7 +184,7 @@
|
||||||
result: input:
|
result: input:
|
||||||
result
|
result
|
||||||
// {
|
// {
|
||||||
"${input}" = nixpkgs-unstable.lib.nixosSystem {
|
"${input}" = nixpkgs.lib.nixosSystem {
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
modules =
|
modules =
|
||||||
let
|
let
|
||||||
|
|
@ -196,10 +197,8 @@
|
||||||
disko.nixosModules.disko
|
disko.nixosModules.disko
|
||||||
authentik.nixosModules.default
|
authentik.nixosModules.default
|
||||||
mailserver.nixosModules.mailserver
|
mailserver.nixosModules.mailserver
|
||||||
gradient.nixosModules.default
|
|
||||||
sops.nixosModules.sops
|
|
||||||
{
|
{
|
||||||
_module.args = { inherit self inputs modulesPath; };
|
_module.args = { inherit self modulesPath; };
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,210 +0,0 @@
|
||||||
# Git Host - Forgejo
|
|
||||||
|
|
||||||
Forgejo git server at 141.56.51.7 running in an LXC container.
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
- **Hostname**: git
|
|
||||||
- **FQDN**: git.adm.htw.stura-dresden.de
|
|
||||||
- **IP Address**: 141.56.51.7
|
|
||||||
- **Type**: Proxmox LXC Container
|
|
||||||
- **Services**: Forgejo, Nginx (reverse proxy), OpenSSH
|
|
||||||
|
|
||||||
## Services
|
|
||||||
|
|
||||||
### Forgejo
|
|
||||||
|
|
||||||
Forgejo is a self-hosted Git service (fork of Gitea) providing:
|
|
||||||
- Git repository hosting
|
|
||||||
- Web interface for repository management
|
|
||||||
- Issue tracking
|
|
||||||
- Pull requests
|
|
||||||
- OAuth2 integration support
|
|
||||||
|
|
||||||
**Configuration**:
|
|
||||||
- **Socket**: `/run/forgejo/forgejo.sock` (Unix socket)
|
|
||||||
- **Root URL**: https://git.adm.htw.stura-dresden.de
|
|
||||||
- **Protocol**: HTTP over Unix socket (Nginx handles TLS)
|
|
||||||
|
|
||||||
### Nginx
|
|
||||||
|
|
||||||
Nginx acts as a reverse proxy between the network and Forgejo:
|
|
||||||
- Receives HTTPS requests (TLS termination)
|
|
||||||
- Forwards to Forgejo via Unix socket
|
|
||||||
- Manages ACME/Let's Encrypt certificates
|
|
||||||
- WebSocket support enabled for live updates
|
|
||||||
|
|
||||||
### OAuth2 Auto-Registration
|
|
||||||
|
|
||||||
OAuth2 client auto-registration is enabled:
|
|
||||||
- `ENABLE_AUTO_REGISTRATION = true`
|
|
||||||
- `REGISTER_EMAIL_CONFIRM = false`
|
|
||||||
- Username field: email
|
|
||||||
|
|
||||||
This allows users to register automatically via OAuth2 providers without manual approval.
|
|
||||||
|
|
||||||
## Deployment
|
|
||||||
|
|
||||||
See the [main README](../../README.md) for deployment methods.
|
|
||||||
|
|
||||||
### Initial Installation
|
|
||||||
|
|
||||||
**Using nixos-anywhere:**
|
|
||||||
```bash
|
|
||||||
nix run github:nix-community/nixos-anywhere -- --flake .#git --target-host root@141.56.51.7
|
|
||||||
```
|
|
||||||
|
|
||||||
**Using container tarball:**
|
|
||||||
```bash
|
|
||||||
nix build .#containers-git
|
|
||||||
scp result/tarball/nixos-system-x86_64-linux.tar.xz root@proxmox-host:/var/lib/vz/template/cache/
|
|
||||||
pct create 107 /var/lib/vz/template/cache/nixos-system-x86_64-linux.tar.xz \
|
|
||||||
--hostname git \
|
|
||||||
--net0 name=eth0,bridge=vmbr0,ip=141.56.51.7/24,gw=141.56.51.254 \
|
|
||||||
--memory 2048 \
|
|
||||||
--cores 2 \
|
|
||||||
--rootfs local-lvm:8 \
|
|
||||||
--unprivileged 1 \
|
|
||||||
--features nesting=1
|
|
||||||
pct start 107
|
|
||||||
```
|
|
||||||
|
|
||||||
### Updates
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# From local machine
|
|
||||||
nixos-rebuild switch --flake .#git --target-host root@141.56.51.7
|
|
||||||
|
|
||||||
# Or use auto-generated script
|
|
||||||
nix run .#git-update
|
|
||||||
```
|
|
||||||
|
|
||||||
## Post-Deployment Steps
|
|
||||||
|
|
||||||
After deploying for the first time:
|
|
||||||
|
|
||||||
1. **Access the web interface:**
|
|
||||||
```
|
|
||||||
https://git.adm.htw.stura-dresden.de
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Complete initial setup:**
|
|
||||||
- Create the first admin account via web UI
|
|
||||||
- Configure any additional settings
|
|
||||||
- Set up SSH keys for git access
|
|
||||||
|
|
||||||
3. **Configure OAuth2 (optional):**
|
|
||||||
- If using an external identity provider (e.g., authentik)
|
|
||||||
- Add OAuth2 application in the provider
|
|
||||||
- Configure OAuth2 settings in Forgejo admin panel
|
|
||||||
- Auto-registration is already enabled in configuration
|
|
||||||
|
|
||||||
4. **Set up repositories:**
|
|
||||||
- Create organizations
|
|
||||||
- Create repositories
|
|
||||||
- Configure access permissions
|
|
||||||
|
|
||||||
## Integration with Proxy
|
|
||||||
|
|
||||||
The central proxy at 141.56.51.1 handles:
|
|
||||||
- **SNI routing**: Inspects TLS handshake and routes HTTPS traffic for git.adm.htw.stura-dresden.de
|
|
||||||
- **HTTP routing**: Routes HTTP traffic based on Host header
|
|
||||||
- **ACME challenges**: Forwards `/.well-known/acme-challenge/` requests to this host for Let's Encrypt verification
|
|
||||||
- **Auto-redirect**: Redirects HTTP to HTTPS (except ACME challenges)
|
|
||||||
|
|
||||||
This host handles its own TLS certificates via ACME. The proxy passes through encrypted traffic without decryption.
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Forgejo socket permissions
|
|
||||||
|
|
||||||
If Forgejo fails to start or Nginx cannot connect:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Check socket exists
|
|
||||||
ls -l /run/forgejo/forgejo.sock
|
|
||||||
|
|
||||||
# Check Forgejo service status
|
|
||||||
systemctl status forgejo
|
|
||||||
|
|
||||||
# Check Nginx service status
|
|
||||||
systemctl status nginx
|
|
||||||
|
|
||||||
# View Forgejo logs
|
|
||||||
journalctl -u forgejo -f
|
|
||||||
```
|
|
||||||
|
|
||||||
**Solution**: Ensure the Forgejo user has proper permissions and the socket path is correct in both Forgejo and Nginx configurations.
|
|
||||||
|
|
||||||
### Nginx proxy configuration
|
|
||||||
|
|
||||||
If the web interface is unreachable:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Check Nginx configuration
|
|
||||||
nginx -t
|
|
||||||
|
|
||||||
# View Nginx error logs
|
|
||||||
journalctl -u nginx -f
|
|
||||||
|
|
||||||
# Test socket connection
|
|
||||||
curl --unix-socket /run/forgejo/forgejo.sock http://localhost/
|
|
||||||
```
|
|
||||||
|
|
||||||
**Solution**: Verify the `proxyPass` directive in Nginx configuration points to the correct Unix socket.
|
|
||||||
|
|
||||||
### SSH access issues
|
|
||||||
|
|
||||||
If git operations over SSH fail:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Check SSH service
|
|
||||||
systemctl status sshd
|
|
||||||
|
|
||||||
# Test SSH connection
|
|
||||||
ssh -T git@git.adm.htw.stura-dresden.de
|
|
||||||
|
|
||||||
# Check Forgejo SSH settings
|
|
||||||
cat /var/lib/forgejo/custom/conf/app.ini | grep -A 5 "\[server\]"
|
|
||||||
```
|
|
||||||
|
|
||||||
**Solution**: Ensure SSH keys are properly added to user accounts and SSH daemon is running.
|
|
||||||
|
|
||||||
### ACME certificate issues
|
|
||||||
|
|
||||||
If HTTPS is not working:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Check ACME certificate status
|
|
||||||
systemctl status acme-git.adm.htw.stura-dresden.de
|
|
||||||
|
|
||||||
# View ACME logs
|
|
||||||
journalctl -u acme-git.adm.htw.stura-dresden.de -f
|
|
||||||
|
|
||||||
# Manually trigger certificate renewal
|
|
||||||
systemctl start acme-git.adm.htw.stura-dresden.de
|
|
||||||
```
|
|
||||||
|
|
||||||
**Solution**: Verify DNS points to proxy (141.56.51.1) and proxy is forwarding ACME challenges correctly.
|
|
||||||
|
|
||||||
## Files and Directories
|
|
||||||
|
|
||||||
- **Configuration**: `/nix/store/.../forgejo/` (managed by Nix)
|
|
||||||
- **Data directory**: `/var/lib/forgejo/`
|
|
||||||
- **Custom config**: `/var/lib/forgejo/custom/conf/app.ini`
|
|
||||||
- **Repositories**: `/var/lib/forgejo/data/gitea-repositories/`
|
|
||||||
- **Socket**: `/run/forgejo/forgejo.sock`
|
|
||||||
|
|
||||||
## Network
|
|
||||||
|
|
||||||
- **Interface**: eth0 (LXC container)
|
|
||||||
- **IP**: 141.56.51.7/24
|
|
||||||
- **Gateway**: 141.56.51.254
|
|
||||||
- **Firewall**: Ports 22, 80, 443 allowed
|
|
||||||
|
|
||||||
## See Also
|
|
||||||
|
|
||||||
- [Main README](../../README.md) - Deployment methods and architecture
|
|
||||||
- [Proxy README](../proxy/README.md) - How the central proxy routes traffic
|
|
||||||
- [Forgejo Documentation](https://forgejo.org/docs/latest/)
|
|
||||||
- [NixOS Forgejo Options](https://search.nixos.org/options?query=services.forgejo)
|
|
||||||
|
|
@ -1,95 +0,0 @@
|
||||||
{
|
|
||||||
config,
|
|
||||||
inputs,
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
modulesPath,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
"${modulesPath}/virtualisation/proxmox-lxc.nix"
|
|
||||||
];
|
|
||||||
|
|
||||||
sops = {
|
|
||||||
defaultSopsFile = ./secrets.sops.yaml;
|
|
||||||
secrets = {
|
|
||||||
"gradient-jwt".owner = "gradient";
|
|
||||||
"gradient-crypt".owner = "gradient";
|
|
||||||
"gradient-worker".owner = "gradient-worker";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
networking = {
|
|
||||||
hostName = "gradient";
|
|
||||||
fqdn = "gradient.adm.htw.stura-dresden.de";
|
|
||||||
interfaces.eth0.ipv4.addresses = [
|
|
||||||
{
|
|
||||||
address = "141.56.51.127";
|
|
||||||
prefixLength = 24;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
defaultGateway = {
|
|
||||||
address = "141.56.51.254";
|
|
||||||
interface = "eth0";
|
|
||||||
};
|
|
||||||
firewall.allowedTCPPorts = [
|
|
||||||
80
|
|
||||||
443
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
services = {
|
|
||||||
openssh.enable = true;
|
|
||||||
|
|
||||||
gradient = {
|
|
||||||
enable = true;
|
|
||||||
frontend.enable = true;
|
|
||||||
domain = "${config.networking.fqdn}";
|
|
||||||
jwtSecretFile = "/run/secrets/gradient-jwt";
|
|
||||||
cryptSecretFile = "/run/secrets/gradient-crypt";
|
|
||||||
configurePostgres = true;
|
|
||||||
configureNginx = true;
|
|
||||||
# serveCache = true;
|
|
||||||
reportErrors = true;
|
|
||||||
|
|
||||||
worker = {
|
|
||||||
enable = true;
|
|
||||||
serverUrl = "ws://127.0.0.1:3000/proto";
|
|
||||||
workerId = "8f56dd3a-5698-4512-8bf7-ab8dcfaed46c";
|
|
||||||
peersFile = "/run/secrets/gradient-worker-peers";
|
|
||||||
capabilities = {
|
|
||||||
fetch = true;
|
|
||||||
eval = true;
|
|
||||||
build = true;
|
|
||||||
};
|
|
||||||
packages.nix = inputs.nixpkgs-unstable.legacyPackages.x86_64-linux.nix;
|
|
||||||
settings = {
|
|
||||||
logLevel = {
|
|
||||||
default = "debug";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
nginx.commonHttpConfig = ''
|
|
||||||
real_ip_header proxy_protocol;
|
|
||||||
set_real_ip_from 141.56.51.1/32;
|
|
||||||
'';
|
|
||||||
nginx.virtualHosts."${config.networking.fqdn}".listen = [
|
|
||||||
{
|
|
||||||
port = 80;
|
|
||||||
addr = "0.0.0.0";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
port = 443;
|
|
||||||
addr = "0.0.0.0";
|
|
||||||
ssl = true;
|
|
||||||
proxyProtocol = true;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
system.stateVersion = "25.11";
|
|
||||||
}
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
gradient-jwt: ENC[AES256_GCM,data:0RgUOHbz5qtBOE1+wldyhzE6b4275JTkzdjgQBbVUnHtNVvqmQUs94JGfB2HRteVJS2pRmRxyh+YYUpuErkmaw==,iv:C6AqWjVs6MGjTJ/QEFq9kz7kSglMXi+rtlmkEK0i4r0=,tag:HvmCN947JveYFDITZfAEMA==,type:str]
|
|
||||||
gradient-crypt: ENC[AES256_GCM,data:j6KRaxQItKtolZXPxN1Rp4NalX5rYnHvQzL/R0naobgM2nMUiOJJeKiZ5yooXbaNC1wrwWNfMrNDYkm8bxVJeA==,iv:2wiiyJu3u9cEwwos0DhgKiwp0qYSw1z6MdOvpWsf+Is=,tag:GOfN78rlovnPXgiCAE9diA==,type:str]
|
|
||||||
gradient-worker: ENC[AES256_GCM,data:IktOl14QzBee16ZxZZMmseMomlyF+teJoxsNmqDXcPHq4ZZv7QWDQAjIct4hz1CHofaBfXzVM372WSLTX51/zw==,iv:OZsC9EX4fRUv7Q9AbnXBaskX9hS/wgFctOepz39NyDU=,tag:GHPx4yXb7ta5pj4+yI2PRQ==,type:str]
|
|
||||||
sops:
|
|
||||||
age:
|
|
||||||
- recipient: age1kfxhahmxprheer63shv68slpmk5qz29nyx3kp4q6n879zz9ha34q04n50x
|
|
||||||
enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2OHc0aWRocmx2QkUzcnFa
|
|
||||||
T3Z5MWp3U2I1c2RZMytnU1hkd0p4ZHNWSW5vCmFuZHBJYjMrSUwranVDNHR1RmFr
|
|
||||||
dVhSVmdPUGd1czFjM3p3dlBLcTU0T1UKLS0tIDl1eHBkL1lBUWh0ckhya1dJTjdY
|
|
||||||
WmhPVEl3ZytOdmdaQ3pkN2lLTnRPMzAKCKj7VvRPTBXfsqa6FnJi3ZkWNUXN8JG8
|
|
||||||
NlcK9QL/pMoExpoLHfw8ram4Y2i9up4oONeA2iKR12Dh86Y8RUUJfg==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
- recipient: age16m8vvvpw4azfy6gygtstyyj6nd2sf848f7f7argaghwhct38muxsgxpeek
|
|
||||||
enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRVXNoVktTL0VvdVIrVWx6
|
|
||||||
cFpLMnhJcmFWYlVKWWZIVUR1NGMzRWhOWngwClVRZ092dDFEMHJ3d3JkdFkwVVI2
|
|
||||||
YW9BK0hBNnB6UmM0bzBYYVNqS0QxcFEKLS0tIHljSm03TTRjTVlSam4xN2NhMUJ6
|
|
||||||
aDNFUi9SL1BhZHMxVUFkTzR6bk16cWsKeS3Y8b/WlvdgmY5yLjTfTHJwBZoZ7RU8
|
|
||||||
GPLB8ezNB3U7XxO05hwlUQJbTkMVhSzu+nKfEavdS1KMoXaxfxhrwA==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
lastmodified: "2026-04-22T08:34:30Z"
|
|
||||||
mac: ENC[AES256_GCM,data:74FyYHQ/bMZ3wxodMlvAXYl2UWNkv8arWSDeJwCEfRWz05bzXWy6UaMLWc+dSoqJsVvT3SRVuBMrtilsckVqCVQ4C96c730IVWB/b5juIXtEsp1JiWgS+F3yC992HDGmoGnAkSE/vzZBu3DRA8/eMwkoTtGscpDhnAzUVrkCNUk=,iv:BzhopR3jxZyKZhwRxh1lKaIaGgE5IbIe/AG35D1juZA=,tag:frnRzapbiU49TpkISZ4GEQ==,type:str]
|
|
||||||
unencrypted_suffix: _unencrypted
|
|
||||||
version: 3.12.1
|
|
||||||
|
|
@ -20,49 +20,22 @@
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
defaultGateway.address = "141.56.51.254";
|
defaultGateway.address = "141.56.51.254";
|
||||||
firewall.enable = false;
|
firewall = {
|
||||||
|
allowedTCPPorts = [
|
||||||
|
22
|
||||||
|
53 # DNS
|
||||||
|
80
|
||||||
|
443
|
||||||
|
1005
|
||||||
|
2142
|
||||||
|
];
|
||||||
|
allowedUDPPorts = [
|
||||||
|
53 # DNS
|
||||||
|
123 # NTP
|
||||||
|
];
|
||||||
|
};
|
||||||
nftables = {
|
nftables = {
|
||||||
enable = true;
|
enable = true;
|
||||||
ruleset = ''
|
|
||||||
table inet filter {
|
|
||||||
set blacklist4 {
|
|
||||||
type ipv4_addr
|
|
||||||
flags interval
|
|
||||||
# manage: nft add element inet filter blacklist4 { 1.2.3.0/24 }
|
|
||||||
}
|
|
||||||
|
|
||||||
set blacklist6 {
|
|
||||||
type ipv6_addr
|
|
||||||
flags interval
|
|
||||||
# manage: nft add element inet filter blacklist6 { 2001:db8::/32 }
|
|
||||||
}
|
|
||||||
|
|
||||||
chain input {
|
|
||||||
type filter hook input priority filter; policy drop;
|
|
||||||
|
|
||||||
iif "lo" accept
|
|
||||||
ct state established,related accept
|
|
||||||
|
|
||||||
ip saddr @blacklist4 drop
|
|
||||||
ip6 saddr @blacklist6 drop
|
|
||||||
|
|
||||||
# public ports
|
|
||||||
tcp dport { 80, 443, 1005, 2142 } accept
|
|
||||||
|
|
||||||
# lan-only: dns and ntp
|
|
||||||
ip saddr 141.56.51.0/24 tcp dport 53 accept
|
|
||||||
ip saddr 141.56.51.0/24 udp dport { 53, 123 } accept
|
|
||||||
}
|
|
||||||
|
|
||||||
chain forward {
|
|
||||||
type filter hook forward priority filter; policy drop;
|
|
||||||
}
|
|
||||||
|
|
||||||
chain output {
|
|
||||||
type filter hook output priority filter; policy accept;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -479,7 +452,6 @@
|
||||||
|
|
||||||
frontend http-in
|
frontend http-in
|
||||||
bind *:80
|
bind *:80
|
||||||
mode http
|
|
||||||
tcp-request connection expect-proxy layer4 if { src 178.104.18.93 }
|
tcp-request connection expect-proxy layer4 if { src 178.104.18.93 }
|
||||||
maxconn 60000
|
maxconn 60000
|
||||||
backlog 8192
|
backlog 8192
|
||||||
|
|
@ -503,8 +475,8 @@
|
||||||
prev: name: value:
|
prev: name: value:
|
||||||
prev
|
prev
|
||||||
+ ''
|
+ ''
|
||||||
http-request redirect scheme https code 301 if !is_acme is_${name}
|
|
||||||
use_backend ${name}_80 if is_${name}
|
use_backend ${name}_80 if is_${name}
|
||||||
|
http-request redirect scheme https code 301 if !is_acme is_${name}
|
||||||
''
|
''
|
||||||
) "" forwards}
|
) "" forwards}
|
||||||
|
|
||||||
|
|
@ -638,47 +610,6 @@
|
||||||
|
|
||||||
stura.monitoring.extraLogInputs = [ "haproxy_geoip" ];
|
stura.monitoring.extraLogInputs = [ "haproxy_geoip" ];
|
||||||
|
|
||||||
users.users.root.packages = [
|
|
||||||
(pkgs.writeShellScriptBin "nft-blacklist" ''
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
echo "Usage: nft-blacklist <add|del> <ip-or-cidr>"
|
|
||||||
echo " add - add entry to blacklist set"
|
|
||||||
echo " del - remove entry from blacklist set"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
[[ $# -ne 2 ]] && usage
|
|
||||||
|
|
||||||
ACTION="$1"
|
|
||||||
ADDR="$2"
|
|
||||||
|
|
||||||
if [[ "$ADDR" == *:* ]]; then
|
|
||||||
SET="blacklist6"
|
|
||||||
elif [[ "$ADDR" == *.* ]]; then
|
|
||||||
SET="blacklist4"
|
|
||||||
else
|
|
||||||
echo "Error: cannot determine address family for '$ADDR'" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
case "$ACTION" in
|
|
||||||
add)
|
|
||||||
${pkgs.nftables}/bin/nft add element inet filter "$SET" "{ $ADDR }"
|
|
||||||
echo "Added $ADDR to $SET"
|
|
||||||
;;
|
|
||||||
del)
|
|
||||||
${pkgs.nftables}/bin/nft delete element inet filter "$SET" "{ $ADDR }"
|
|
||||||
echo "Removed $ADDR from $SET"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
usage
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
'')
|
|
||||||
];
|
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -134,9 +134,9 @@
|
||||||
|
|
||||||
#### Der StuRa speichert nicht!
|
#### Der StuRa speichert nicht!
|
||||||
services.nginx.logError = ''/dev/null emerg'';
|
services.nginx.logError = ''/dev/null emerg'';
|
||||||
# services.nginx.appendHttpConfig = ''
|
services.nginx.appendHttpConfig = ''
|
||||||
# access_log off;
|
access_log off;
|
||||||
# '';
|
'';
|
||||||
services.nginx.commonHttpConfig = ''
|
services.nginx.commonHttpConfig = ''
|
||||||
real_ip_header proxy_protocol;
|
real_ip_header proxy_protocol;
|
||||||
set_real_ip_from 141.56.51.1/32;
|
set_real_ip_from 141.56.51.1/32;
|
||||||
|
|
|
||||||
|
|
@ -38,44 +38,16 @@
|
||||||
"9.9.9.9"
|
"9.9.9.9"
|
||||||
"1.1.1.1"
|
"1.1.1.1"
|
||||||
];
|
];
|
||||||
firewall.enable = false;
|
firewall = {
|
||||||
|
enable = true;
|
||||||
|
allowedTCPPorts = [
|
||||||
|
22
|
||||||
|
80
|
||||||
|
443
|
||||||
|
];
|
||||||
|
};
|
||||||
nftables = {
|
nftables = {
|
||||||
enable = true;
|
enable = true;
|
||||||
ruleset = ''
|
|
||||||
table inet filter {
|
|
||||||
set blacklist4 {
|
|
||||||
type ipv4_addr
|
|
||||||
flags interval
|
|
||||||
# manage at runtime: nft add element inet filter blacklist4 { 1.2.3.0/24 }
|
|
||||||
}
|
|
||||||
|
|
||||||
set blacklist6 {
|
|
||||||
type ipv6_addr
|
|
||||||
flags interval
|
|
||||||
# manage at runtime: nft add element inet filter blacklist6 { 2001:db8::/32 }
|
|
||||||
}
|
|
||||||
|
|
||||||
chain input {
|
|
||||||
type filter hook input priority filter; policy drop;
|
|
||||||
|
|
||||||
iif "lo" accept
|
|
||||||
ct state established,related accept
|
|
||||||
|
|
||||||
ip saddr @blacklist4 drop
|
|
||||||
ip6 saddr @blacklist6 drop
|
|
||||||
|
|
||||||
tcp dport { 22, 80, 443 } accept
|
|
||||||
}
|
|
||||||
|
|
||||||
chain forward {
|
|
||||||
type filter hook forward priority filter; policy drop;
|
|
||||||
}
|
|
||||||
|
|
||||||
chain output {
|
|
||||||
type filter hook output priority filter; policy accept;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -130,45 +102,7 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
users.users.root.packages = [
|
environment.systemPackages = with pkgs; [
|
||||||
(pkgs.writeShellScriptBin "nft-blacklist" ''
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
echo "Usage: nft-blacklist <add|del> <ip-or-cidr>"
|
|
||||||
echo " add - add entry to blacklist set"
|
|
||||||
echo " del - remove entry from blacklist set"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
[[ $# -ne 2 ]] && usage
|
|
||||||
|
|
||||||
ACTION="$1"
|
|
||||||
ADDR="$2"
|
|
||||||
|
|
||||||
if [[ "$ADDR" == *:* ]]; then
|
|
||||||
SET="blacklist6"
|
|
||||||
elif [[ "$ADDR" == *.* ]]; then
|
|
||||||
SET="blacklist4"
|
|
||||||
else
|
|
||||||
echo "Error: cannot determine address family for '$ADDR'" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
case "$ACTION" in
|
|
||||||
add)
|
|
||||||
${pkgs.nftables}/bin/nft add element inet filter "$SET" "{ $ADDR }"
|
|
||||||
echo "Added $ADDR to $SET"
|
|
||||||
;;
|
|
||||||
del)
|
|
||||||
${pkgs.nftables}/bin/nft delete element inet filter "$SET" "{ $ADDR }"
|
|
||||||
echo "Removed $ADDR from $SET"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
usage
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
'')
|
|
||||||
];
|
];
|
||||||
|
|
||||||
system.stateVersion = "25.11";
|
system.stateVersion = "25.11";
|
||||||
|
|
|
||||||
|
|
@ -201,8 +201,8 @@
|
||||||
#### https://www.mediawiki.org/wiki/Extension:UserMerge
|
#### https://www.mediawiki.org/wiki/Extension:UserMerge
|
||||||
UserMerge = pkgs.fetchzip {
|
UserMerge = pkgs.fetchzip {
|
||||||
# url = "https://extdist.wmflabs.org/dist/extensions/UserMerge-REL1_43-ed4a689.tar.gz";
|
# url = "https://extdist.wmflabs.org/dist/extensions/UserMerge-REL1_43-ed4a689.tar.gz";
|
||||||
url = "https://extdist.wmflabs.org/dist/extensions/UserMerge-REL1_45-433f6c2.tar.gz";
|
url = "https://extdist.wmflabs.org/dist/extensions/UserMerge-REL1_45-437c211.tar.gz";
|
||||||
sha256 = "sha256-JyY4pJNBKQ9bOKrilPWCheZ5ihWwPM6ZJ0qHsZ3coPk=";
|
sha256 = "sha256-DWdcvubqZkvtywuDEOjui68WYuETt5hGpJJlpZ+pJgE=";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
18
keys/.gitignore
vendored
Normal file
18
keys/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Prevent accidental commit of private keys
|
||||||
|
*.key
|
||||||
|
*.priv
|
||||||
|
*.private
|
||||||
|
*_priv
|
||||||
|
*-priv
|
||||||
|
*.sec
|
||||||
|
*secret*
|
||||||
|
|
||||||
|
# Only allow public keys
|
||||||
|
!*.asc
|
||||||
|
!*.gpg
|
||||||
|
!*.pub
|
||||||
|
!*.age
|
||||||
|
|
||||||
|
# Allow this gitignore and README
|
||||||
|
!.gitignore
|
||||||
|
!README.md
|
||||||
40
keys/README.md
Normal file
40
keys/README.md
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
# Keys Directory
|
||||||
|
|
||||||
|
This directory contains GPG/age public keys for sops encryption.
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
|
||||||
|
- `hosts/` - Host-specific public keys (for servers to decrypt their own secrets)
|
||||||
|
- `users/` - User/admin public keys (for team members to decrypt secrets)
|
||||||
|
|
||||||
|
## Adding Keys
|
||||||
|
|
||||||
|
### GPG Keys
|
||||||
|
|
||||||
|
Export your GPG public key:
|
||||||
|
```bash
|
||||||
|
gpg --export --armor YOUR_KEY_ID > keys/users/yourname.asc
|
||||||
|
```
|
||||||
|
|
||||||
|
Export a host's public key:
|
||||||
|
```bash
|
||||||
|
gpg --export --armor HOST_KEY_ID > keys/hosts/hostname.asc
|
||||||
|
```
|
||||||
|
|
||||||
|
### Age Keys
|
||||||
|
|
||||||
|
For age keys, save the public key to a file:
|
||||||
|
```bash
|
||||||
|
echo "age1..." > keys/users/yourname.age
|
||||||
|
echo "age1..." > keys/hosts/hostname.age
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
When you enter the dev shell (`nix develop`), all keys in these directories will be automatically imported into your GPG keyring via the sops-import-keys-hook.
|
||||||
|
|
||||||
|
## Important
|
||||||
|
|
||||||
|
- Only commit **public** keys (.asc, .age files with public keys)
|
||||||
|
- Never commit private keys
|
||||||
|
- Update `.sops.yaml` to reference the fingerprints/keys for access control
|
||||||
0
keys/hosts/.gitkeep
Normal file
0
keys/hosts/.gitkeep
Normal file
0
keys/users/.gitkeep
Normal file
0
keys/users/.gitkeep
Normal file
Loading…
Add table
Add a link
Reference in a new issue