Compare commits

...

13 Commits

13 changed files with 275 additions and 44 deletions

View File

@@ -10,19 +10,28 @@ in {
enable = true;
openFirewall = true;
port = 8753;
mutableSettings = false;
settings = {
http = {address = "127.0.0.1:${toString port}";};
users = mapAttrsToList (name: password: {inherit name password;}) {
"admin" = "$2a$12$ciAyKG13D2ViEsy6fACxGu.1qEwwrAfPVgaVQdYgmkmvODHYuVWPa";
"admin" = "$2y$10$1oOiKeJJFSmdc8s8QYUZeeNCHLBAb51BbpLdDjoexUI/0KDHlV8d6";
};
theme = "dark";
dns = {
bootstrap_dns = [
"1.1.1.1"
"8.8.8.8"
];
bind_hosts = [
"127.0.0.1"
(elemAt config.networking.interfaces."eno1".ipv4.addresses 0).address
"100.86.139.22"
];
upstram_dns = ["9.9.9.9"];
upstram_dns = [
# "9.9.9.9"
"1.1.1.1"
"8.8.8.8"
];
};
filtering = {
rewrites = mkIf config.services.caddy.enable (pipe config.services.caddy.virtualHosts [
@@ -30,6 +39,7 @@ in {
(mapAttrsToList (domain: _: {
domain = removePrefix "https://" (removePrefix "http://" domain);
answer = "100.86.139.22";
enabled = true;
}))
]);
parental_enabled = false;

View File

@@ -14,7 +14,7 @@ in {
services.nextcloud = {
enable = true;
package = pkgs.nextcloud31;
package = pkgs.nextcloud32;
webserver = "caddy";
hostName = "nextcloud.local";
appstoreEnable = false;

View File

@@ -1,5 +1,7 @@
{...}: {
imports = [
# ./admin.nix
./peertube.nix
./analytics.nix
./forge.nix
./websites.nix

View File

@@ -147,7 +147,7 @@ in {
"storage.repo-archive" = {};
"repo-archive" = {};
actions = {
ENABLE = false; # Temporarily
ENABLE = true;
DEFAULT_ACTIONS_URL = "self";
};
};
@@ -171,20 +171,28 @@ in {
services.gitea-actions-runner = {
instances = {
"gitea-runner-1" = {
"gitea-runner" = {
enable = true;
name = "Gitea Runner (${config.networking.hostName}) 1";
url = gitea.settings.server.ROOT_URL;
tokenFile = config.sops.secrets."gitea/actions/token".path;
labels = [
"alpine-3.22:docker://data.forgejo.org/oci/alpine:3.22"
"golang-1.24:docker://data.forgejo.org/oci/golang:1.24-alpine3.22"
"ubuntu-22.04:docker://docker.gitea.com/runner-images:ubuntu-22.04"
"node-latest:docker://node:25-bullseye"
"alpine-latest:docker://data.forgejo.org/oci/alpine:3.23"
"golang-latest:docker://data.forgejo.org/oci/golang:1.25-alpine3.23"
];
};
};
};
users.users.gitea = {
isSystemUser = true;
useDefaultShell = true;
group = "gitea";
extraGroups = ["gitea"];
home = config.services.gitea.stateDir;
};
# systemd.services.gitea-custom = let
# gitea = config.services.gitea;
# rsync = lib.getExe pkgs.rsync;

162
capytal/videos.nix Normal file
View File

@@ -0,0 +1,162 @@
{
config,
lib,
pkgs,
...
}: let
cfg = config.services.peertube;
systemCallsList = [
"@cpu-emulation"
"@debug"
"@keyring"
"@ipc"
"@memlock"
"@mount"
"@obsolete"
"@privileged"
"@setuid"
];
cfgService = {
# Proc filesystem
ProtectProc = "invisible";
# Access write directories
UMask = "0027";
# Capabilities
CapabilityBoundingSet = "";
# Security
NoNewPrivileges = true;
# Sandboxing
ProtectSystem = "strict";
ProtectHome = true;
PrivateTmp = true;
PrivateDevices = true;
PrivateUsers = true;
ProtectClock = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectControlGroups = true;
RestrictNamespaces = true;
LockPersonality = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
RemoveIPC = true;
PrivateMounts = true;
# System Call Filtering
SystemCallArchitectures = "native";
};
in {
services.peertube = {
enable = true;
# localDomain = "watch.capytal.cc";
localDomain = "watch-test.capytal.cc";
listenWeb = 9945;
listenHttp = 9945;
enableWebHttps = false;
database = {
# createLocally = true;
host = "/run/postgresql";
port = config.services.postgresql.settings.port;
passwordFile = config.sops.secrets."peertube/database/password".path;
};
redis.createLocally = true;
configureNginx = true;
settings = {
signup.enabled = false;
object_storage = {
enabled = true;
endpoint = "localhost:3461";
region = "garage";
videos = {
bucket_name = "peertube";
prefix = "hls-videos:";
};
streaming_playlists = {
bucket_name = "peertube";
prefix = "streaming-playlists:";
};
user_exports = {
bucket_name = "peertube";
prefix = "user-exports:";
};
original_video_files = {
bucket_name = "peertube";
prefix = "original-video-files:";
};
captions = {
bucket_name = "peertube";
prefix = "captions:";
};
};
webserver = {
hostname = cfg.localDomain;
port = lib.mkForce 443;
};
};
secrets.secretsFile = config.sops.secrets."peertube/secretsFile".path;
serviceEnvironmentFile = config.sops.secrets."peertube/environment".path;
# TODO: Set up postfix server for forms and contact
};
# TODO: Commit this to upstream nixpkgs?
# HACK: services.peertube.database.createLocally option doesn't respect port
systemd.services.peertube-init-db = {
description = "Initialization database for PeerTube daemon";
after = [
"network.target"
"postgresql.service"
];
requires = ["postgresql.service"];
script = let
psqlSetupCommands = pkgs.writeText "peertube-init.sql" ''
SELECT 'CREATE USER "${cfg.database.user}"' WHERE NOT EXISTS (SELECT FROM pg_roles WHERE rolname = '${cfg.database.user}')\gexec
SELECT 'CREATE DATABASE "${cfg.database.name}" OWNER "${cfg.database.user}" TEMPLATE template0 ENCODING UTF8' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '${cfg.database.name}')\gexec
\c '${cfg.database.name}'
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE EXTENSION IF NOT EXISTS unaccent;
'';
in "${config.services.postgresql.package}/bin/psql -f ${psqlSetupCommands} -p ${toString config.services.postgresql.settings.port}";
serviceConfig =
{
Type = "oneshot";
WorkingDirectory = cfg.package;
# User and group
User = "postgres";
Group = "postgres";
# Sandboxing
RestrictAddressFamilies = ["AF_UNIX"];
MemoryDenyWriteExecute = true;
# System Call Filtering
SystemCallFilter = "~" + lib.concatStringsSep " " (systemCallsList ++ ["@resources"]);
}
// cfgService;
};
services.anubis.instances."peertube" = {
settings = {
BIND = ":${toString (cfg.listenWeb + 2)}";
BIND_NETWORK = "tcp";
METRICS_BIND = ":${toString (cfg.listenWeb + 3)}";
METRICS_BIND_NETWORK = "tcp";
SERVE_ROBOTS_TXT = true;
TARGET = "http://localhost:${toString cfg.listenWeb}";
ED25519_PRIVATE_KEY_HEX_FILE = config.sops.secrets."anubis/peertube/hex_file".path;
};
};
services.caddy.virtualHosts = {
":${toString (cfg.listenWeb + 1)}" = {
extraConfig = ''
reverse_proxy http://localhost${config.services.anubis.instances."peertube".settings.BIND} {
header_up X-Http-Version {http.request.proto}
header_up X-Real-Ip {remote_host}
}
'';
};
};
}

View File

@@ -31,4 +31,9 @@ in {
reverse_proxy http://localhost:${toString cfg-keikos.port}
'';
};
services.caddy.virtualHosts.":${toString (cfg-keikos.port + 2)}" = {
extraConfig = ''
redir https://kois.work{uri} permanent
'';
};
}

View File

@@ -1,22 +1,21 @@
{
config,
lib,
pkgs,
...
}: let
cfg = config.services.postgresql;
cfgadm = config.services.pgadmin;
in {
services.postgresql = {
enable = true;
enableTCPIP = true;
authentication = lib.mkForce ''
#type database DBuser origin-address auth-method
local all all trust
# ipv4
host all all 172.0.0.1/32 trust
host all all 127.0.0.1/32 trust
# ipv6
host all all ::1/128 trust
'';
enable = true;
ensureDatabases = [
"forgejo"
"nextcloud"
@@ -31,7 +30,6 @@ in {
ensureDBOwnership = true;
}
];
enableTCPIP = true;
settings = {
port = 3245;
};

View File

@@ -99,7 +99,10 @@ with lib; {
prefixLength = 24;
}
];
nameservers = ["9.9.9.9"];
nameservers = [
"1.1.1.1"
"8.8.8.8"
];
};
# SSH/Mosh configuration

42
flake.lock generated
View File

@@ -601,16 +601,16 @@
]
},
"locked": {
"lastModified": 1757808926,
"narHash": "sha256-K6PEI5PYY94TVMH0mX3MbZNYFme7oNRKml/85BpRRAo=",
"lastModified": 1765859973,
"narHash": "sha256-LN5O0h9GSgcDE/sz4+sLS3CbQALru1x4lh9hrxpeHwI=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "f21d9167782c086a33ad53e2311854a8f13c281e",
"rev": "7df150f0d3857cf68dae443813b27acfb201b2d8",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "release-25.05",
"ref": "release-25.11",
"repo": "home-manager",
"type": "github"
}
@@ -943,11 +943,11 @@
"nixpkgs": "nixpkgs_9"
},
"locked": {
"lastModified": 1760046992,
"narHash": "sha256-gxn4TqMjccch1ULBNlau9t0HANrElrahaRw0r39oROw=",
"lastModified": 1765921137,
"narHash": "sha256-u4qyEOZm1+2LQDlG24smmEToO/r1T08s7MCYzE/DnjE=",
"ref": "refs/heads/main",
"rev": "d9021491c727caceb47ec2f5a057e9d197ce6f1d",
"revCount": 19905,
"rev": "96edd617d6daac89d00c080df561818b2fcd7da2",
"revCount": 19980,
"type": "git",
"url": "https://code.capytal.cc/loreddev/gitea"
},
@@ -1093,11 +1093,11 @@
},
"nixpkgs-unstable_2": {
"locked": {
"lastModified": 1757745802,
"narHash": "sha256-hLEO2TPj55KcUFUU1vgtHE9UEIOjRcH/4QbmfHNF820=",
"lastModified": 1765779637,
"narHash": "sha256-KJ2wa/BLSrTqDjbfyNx70ov/HdgNBCBBSQP3BIzKnv4=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "c23193b943c6c689d70ee98ce3128239ed9e32d1",
"rev": "1306659b587dc277866c7b69eb97e5f07864d8c4",
"type": "github"
},
"original": {
@@ -1109,16 +1109,16 @@
},
"nixpkgs_10": {
"locked": {
"lastModified": 1757810152,
"narHash": "sha256-Vp9K5ol6h0J90jG7Rm4RWZsCB3x7v5VPx588TQ1dkfs=",
"lastModified": 1765762245,
"narHash": "sha256-3iXM/zTqEskWtmZs3gqNiVtRTsEjYAedIaLL0mSBsrk=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "9a094440e02a699be5c57453a092a8baf569bdad",
"rev": "c8cfcd6ccd422e41cc631a0b73ed4d5a925c393d",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-25.05",
"ref": "nixos-25.11",
"repo": "nixpkgs",
"type": "github"
}
@@ -1237,11 +1237,11 @@
},
"nixpkgs_9": {
"locked": {
"lastModified": 1758690382,
"narHash": "sha256-NY3kSorgqE5LMm1LqNwGne3ZLMF2/ILgLpFr1fS4X3o=",
"lastModified": 1765779637,
"narHash": "sha256-KJ2wa/BLSrTqDjbfyNx70ov/HdgNBCBBSQP3BIzKnv4=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "e643668fd71b949c53f8626614b21ff71a07379d",
"rev": "1306659b587dc277866c7b69eb97e5f07864d8c4",
"type": "github"
},
"original": {
@@ -1382,11 +1382,11 @@
]
},
"locked": {
"lastModified": 1758007585,
"narHash": "sha256-HYnwlbY6RE5xVd5rh0bYw77pnD8lOgbT4mlrfjgNZ0c=",
"lastModified": 1765836173,
"narHash": "sha256-hWRYfdH2ONI7HXbqZqW8Q1y9IRbnXWvtvt/ONZovSNY=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "f77d4cfa075c3de66fc9976b80e0c4fc69e2c139",
"rev": "443a7f2e7e118c4fc63b7fae05ab3080dd0e5c63",
"type": "github"
},
"original": {

View File

@@ -1,10 +1,10 @@
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05";
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11";
nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable";
home-manager = {
url = "github:nix-community/home-manager/release-25.05";
url = "github:nix-community/home-manager/release-25.11";
inputs.nixpkgs.follows = "nixpkgs";
};
@@ -30,6 +30,10 @@
dot013-nix = {
url = "github:dot013/nix";
};
# tangled = {
# url = "git+https://tangled.org/tangled.org/core";
# };
};
outputs = {
self,
@@ -37,7 +41,24 @@
home-manager,
nixpkgs-unstable,
...
} @ inputs: {
} @ inputs: let
systems = [
"x86_64-linux"
"aarch64-linux"
"x86_64-darwin"
"aarch64-darwin"
];
forAllSystems = f:
nixpkgs.lib.genAttrs systems (
system: let
pkgs = import nixpkgs {inherit system;};
in
f {
inherit pkgs;
inherit (pkgs) lib;
}
);
in {
nixosConfigurations = {
spacestation = nixpkgs.lib.nixosSystem rec {
system = "x86_64-linux";

View File

@@ -158,7 +158,7 @@ in {
};
};
systemd.services.gitea-secrets = mkIf (!cfg.useWizard) {
systemd.services.gitea-secrets = {
description = "Gitea secret bootstrap helper";
script = ''
if [ ! -s '${cfg.secrets.security.SECRET_KEY}' ]; then
@@ -200,7 +200,7 @@ in {
++ optionals (cfg.database.type == "mysql") [
"mysql.service"
]
++ optionals (!cfg.useWizard) [
++ [
"gitea-secrets.service"
];
requires =
@@ -210,7 +210,7 @@ in {
++ optionals (cfg.database.createDatabase && cfg.database.type == "mysql") [
"mysql.service"
]
++ optionals (!cfg.useWizard) [
++ [
"gitea-secrets.service"
];
@@ -218,7 +218,7 @@ in {
# https://github.com/NixOS/nixpkgs/blob/20c4598c84a671783f741e02bf05cbfaf4907cff/nixos/modules/services/misc/forgejo.nix#L696
preStart = ''
# copy custom configuration and generate random secrets if needed
${optionalString (!cfg.useWizard) ''
${''
function gitea_setup {
config='${cfg.customDir}/conf/app.ini'
cp -f '${format.generate "app.ini" cfg.settings}' "$config"

View File

@@ -33,6 +33,7 @@ with lib; {
# Anubis
${config.services.anubis.defaultOptions.user} = [
"anubis/gitea/hex_file"
"anubis/peertube/hex_file"
"anubis/medama/hex_file"
];
@@ -61,6 +62,18 @@ with lib; {
"keiko/env_file"
];
# Peertube
${config.services.peertube.user} = [
"peertube/database/password"
"peertube/environment"
"peertube/secretsFile"
];
# PostgreSQL
${config.users.users.postgres.name} = [
"postgresql/initialScript"
];
# Nextcloud
${config.services.phpfpm.pools.nextcloud.user} = [
"nextcloud/adminpass"

View File

@@ -3,6 +3,8 @@ anubis:
hex_file: ENC[AES256_GCM,data:UlFkdy1MfwaQqDnxtMtg4kH/dMJVl8sk4DMfdaCczHGaPtPuP4ADxcBxqpNkzYnQPxbv5ZXqR4qz8Ur5QHWxUg==,iv:WQHkSMiJEV0IWMVvfxC/EuE/e8QabhJinRHADm7kdSg=,tag:1JRwMp94APRszgBuQ0yaQQ==,type:str]
gitea:
hex_file: ENC[AES256_GCM,data:VeF2FRqZdsYe3A002QLGG8jc5s+Tfr5V4dpO/aZ4Rbh9T/O3XQznocDsmUOvjIysH9wbVwvBXGdH1U3vd0qmVg==,iv:/3VQLK+C76HoCbpZAUQaxOFsiFKDuuP2KWAV0EBasp4=,tag:brqDAaHv7r9DRLBoMMmRqw==,type:str]
peertube:
hex_file: ENC[AES256_GCM,data:1G2MZRpGFVr2Pd2eRlaLyVfYY+DrCtqfaBaC3S/dVrDJr8s7Xw7w622ILNUflZAEcYKCvpI25oNNnCG0pw6L3g==,iv:1VHhQ5Y2gdZeZIadWy2YyCYA8k79Acm0sE4MjWZYChg=,tag:G3u80vSy3hTYcsGCy9HZrg==,type:str]
medama:
hex_file: ENC[AES256_GCM,data:wLRw34+uPWpR5GJuI8Q+nlX4hEx3sMn5mSl/lF5kX0Z8N99Eb6Qj4Emx2mK4dNukYNO8j9blw1/RAL94I+QCjQ==,iv:/dW5Z+S14dByXIUyOyEIxxRFl7e4lZZfBKtukV4s68M=,tag:fELbLVzwIgMJUjhNJw4kYg==,type:str]
cloudflared:
@@ -41,6 +43,13 @@ guz:
password: ENC[AES256_GCM,data:zlO5xSFho7TXjFv62lgFir9SAgn+UE6XjdNEvIAgmQG9oDkthfgxO84wYdI0mQDwRIIs2PmSdBRfo0DPc3hji+ySCrItolPL8g==,iv:MZfhTxwfcbmXh5C6DkQhnY9NQGdE8zEwwvFOHQiUgKY=,tag:JjJN2bYcSXNN3ueGj5RNLg==,type:str]
keiko:
env_file: ENC[AES256_GCM,data:dgHWczdwDxz3yV66F+4lMTRIMvHDBYZ6ycVARQPVT7GcYhelA/5uNks3Sdn1n8vgie7TmZBT9mGv+ePtP4+GMyHo/bOJqvjcXyU9dB30CwxuYOCPefitbKxHwIJxkMJqmXvNr3pl2u0mZWUu3mdGMLI9fF3z8/Tk0xM/g4ZezLGaXcRhUSdQPDiOFt2VKA5IrERnpRP0ey5Jx3tf,iv:gpLQdIBGgMCgR0B7jEZDF+3t85nsOVkdxubBUR+QOWA=,tag:eTgQ2uvWsGPEXkpzj/3Szw==,type:str]
postgresql:
initialScript: ENC[AES256_GCM,data:9ByABGVJgE7+CpWTiRLvN8PM2N4UjRylcFR7zjSeROkpkJQfxaJas0G2kLo9wRXVbp82NlIb8A5kd7pFCfF/GC7G7bqfIiR65yevLJ+SScEnhx2YSd5U1dTNwgaK48Q2b9aACn5qOVCwA0WgKkUZMBH2G6u/9VCHjFWXnoVX1YqQ1IwiCE4aSwGdiSykMQXldLnVDB/CDhir7x6/M+jroW+hrkrmXVXZbM5JRTz4foUEafhjFInZXbPKJl+rgNv//DAG4tYWCOljruRVmtKo9CJm277/8C2jd5NwVUFsBmDuvIQjrSBo25r7UMV+US7JJO2gjw/81QraNy95nTxdIAphTqV4W1eeZIxWwDKul6WvyNwTsa/Zw8nUHmlf1i7NWiy+YaqJHrPWXPnytTNLuFsm34sU5Jair4l4LRkzUW/+wZk3977xbmVbUwimywO7,iv:rOP9dSSnWiJKe30hxD4+klj/JZygcEsskf+71zn5Eu4=,tag:nz11prtg2DiK+EODarIYFA==,type:str]
peertube:
database:
password: ENC[AES256_GCM,data:PUHAXOXMwDVFc7cHihhizQ==,iv:FgUKffolNJrK/hqTnm0ciYdQDl6VjCXeEp+tyfa+Wmo=,tag:Mcxjlcd4Hr+x91Cx4/9p7w==,type:str]
secretsFile: ENC[AES256_GCM,data:3ZlvLnxollbqo7tLKbq81cGcYkbVqhmRe/3h0XOyPDgXtOvaiVKkUeIbbTmhdai4ueQcEF5U7xn0Lc8FZqLE2Q==,iv:H2quDSKPaVNLq91nqHxVvOh/611Ej2prAf1Rd3/8AOQ=,tag:CGqTSJNqiaFoFR21PabwRA==,type:str]
environment: ENC[AES256_GCM,data:z4C957prGW1EoDnnjO1DiW6d4qlIkBwAdE/wXDVSvgwWczz2u6YgDPA+QuIC2OkfcSzlz5kslCoBLtVubiQRnjgUJhXAFXfilD0+cLq82Kak9LAZAkuGyhivTGmNg0rpOh9qamns5hpXXlbu8/VFyCX/XWv6gN0P3GeS+As7QNhm7M9O,iv:qb5kAhljVF45+bluZ6t3kNHZ2+C3g/8pnDjVe+1v6bs=,tag:GYmtgfcyCTxHNpq4rHSXvg==,type:str]
nextcloud:
adminpass: ENC[AES256_GCM,data:RY2BsFDSttpr,iv:Mv22/Ht4Uq0miQjKgbnu37UCk/wZMyc6t9jrWkyXsxI=,tag:ScYTA46R0ZpkeqjhRsYzYg==,type:str]
s3:
@@ -57,7 +66,7 @@ sops:
amRmVkVoS2RqeEs3OXZVeTlsZUVEV28K1WcbGJHT8LMah5b7NN1psiucTl1OfZYO
4T3RDSQMB3qj1TGQSdixjwRRKbMGtL3LXnvkNd+caVi5Z9OkF1O9Yg==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2025-10-10T21:47:17Z"
mac: ENC[AES256_GCM,data:4K5fNM05Mm3VCFTx2lntPUcaW/fznjchMdd26VJURBTED3Hr8wpLyNMFtWqWlKZvVuMyk7VQyyBmysb0clmydHpuDR9TtJSJA+IyIyK6IQJi86mQs7IpcSf4Z6uXA33ed3z2aJWhwA8l+5XtwQjYQbDeME1v/ir7xTeqz8P4STI=,iv:iaXcW+3UumdAR/v4/Pp8ZCqJQ2WmL6fucRFJwTugxrc=,tag:sxUajgkMkYjshIgU24o+/w==,type:str]
lastmodified: "2025-11-30T16:31:04Z"
mac: ENC[AES256_GCM,data:74FbU0xXoMhVt+gYFnl3T3GeWdAzXTR7f3SZztTRwtgyEIX/ktvZsKXaAUstTbz5zjybBr5zlwwXKSIL2bM3R5oSva7LVNTkbLBPSad8/O8iQtq8BSKVVHFhvjBfAbpVmZVlUgNzUCS2X+bZwHO3Tl0KgEYozXPQa66jwTUVF0w=,iv:XebXM0AP+53qxWJMKSjqVJsdwWXwglcGmx1mqKgzcf8=,tag:yniIwNDOrSY7KFYDggb+/g==,type:str]
unencrypted_suffix: _unencrypted
version: 3.10.2