Compare commits
No commits in common. "28daab5d65c6ac29bdb12f1108a6f339d25ebd30" and "c362a58363412f50c550e02a46f13ad790a2cd2c" have entirely different histories.
28daab5d65
...
c362a58363
6 changed files with 1 additions and 409 deletions
|
|
@ -5,7 +5,6 @@
|
||||||
./hardware-configuration.nix
|
./hardware-configuration.nix
|
||||||
# Add further modules here later, e.g.:
|
# Add further modules here later, e.g.:
|
||||||
./programs.nix
|
./programs.nix
|
||||||
./forgejo.nix
|
|
||||||
# ./modules/nextcloud.nix
|
# ./modules/nextcloud.nix
|
||||||
# ./modules/wireguard.nix
|
# ./modules/wireguard.nix
|
||||||
# ./modules/docker.nix
|
# ./modules/docker.nix
|
||||||
|
|
@ -51,34 +50,12 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.nginx = {
|
|
||||||
enable = true;
|
|
||||||
recommendedGzipSettings = true;
|
|
||||||
recommendedOptimisation = true;
|
|
||||||
recommendedTlsSettings = true;
|
|
||||||
recommendedProxySettings = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
security.acme = { acceptTerms = true; defaults.email = "nio24@pm.me"; };
|
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# TIMEZONE & LOCALISATION
|
# TIMEZONE & LOCALISATION
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
time.timeZone = "Europe/Berlin";
|
time.timeZone = "Europe/Berlin";
|
||||||
i18n.defaultLocale = "en_US.UTF-8";
|
i18n.defaultLocale = "de_DE.UTF-8";
|
||||||
|
|
||||||
i18n.extraLocaleSettings = {
|
|
||||||
LC_ADDRESS = "de_DE.UTF-8";
|
|
||||||
LC_IDENTIFICATION = "de_DE.UTF-8";
|
|
||||||
LC_MEASUREMENT = "de_DE.UTF-8";
|
|
||||||
LC_MONETARY = "de_DE.UTF-8";
|
|
||||||
LC_NAME = "de_DE.UTF-8";
|
|
||||||
LC_NUMERIC = "de_DE.UTF-8";
|
|
||||||
LC_PAPER = "de_DE.UTF-8";
|
|
||||||
LC_TELEPHONE = "de_DE.UTF-8";
|
|
||||||
LC_TIME = "de_DE.UTF-8";
|
|
||||||
};
|
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# SSH
|
# SSH
|
||||||
|
|
|
||||||
27
flake.lock
generated
27
flake.lock
generated
|
|
@ -1,27 +0,0 @@
|
||||||
{
|
|
||||||
"nodes": {
|
|
||||||
"nixpkgs": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1778430510,
|
|
||||||
"narHash": "sha256-Ti+ZBvW6yrWWAg2szExVTwCd4qOJ3KlVr1tFHfyfi8Q=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "8fd9daa3db09ced9700431c5b7ad0e8ba199b575",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixos-25.11",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": "nixpkgs"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": "root",
|
|
||||||
"version": 7
|
|
||||||
}
|
|
||||||
16
flake.nix
16
flake.nix
|
|
@ -1,16 +0,0 @@
|
||||||
{
|
|
||||||
description = "NixOS Konfiguration";
|
|
||||||
|
|
||||||
inputs = {
|
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
|
|
||||||
};
|
|
||||||
|
|
||||||
outputs = { self, nixpkgs, ... }: {
|
|
||||||
nixosConfigurations.nixos = nixpkgs.lib.nixosSystem {
|
|
||||||
system = "x86_64-linux";
|
|
||||||
modules = [
|
|
||||||
./configuration.nix
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
94
forgejo.nix
94
forgejo.nix
|
|
@ -1,94 +0,0 @@
|
||||||
{ config, pkgs, lib, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
# Kurzreferenzen damit du nicht immer den vollen Pfad schreiben musst.
|
|
||||||
# "cfg" zeigt auf den gesamten forgejo-Konfigurationsblock.
|
|
||||||
# "srv" zeigt auf den server-Unterblock innerhalb von forgejo.
|
|
||||||
cfg = config.services.forgejo;
|
|
||||||
srv = cfg.settings.server;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
# ============================================================
|
|
||||||
# FORGEJO SERVICE
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
services.forgejo = {
|
|
||||||
enable = true;
|
|
||||||
|
|
||||||
# PostgreSQL ist stabiler und performanter als SQLite für den echten Betrieb.
|
|
||||||
# NixOS legt die Datenbank und den User automatisch an.
|
|
||||||
database.type = "postgres";
|
|
||||||
|
|
||||||
# LFS = Large File Storage. Ermöglicht das Versionieren großer Dateien
|
|
||||||
# (z.B. Binaries, Bilder) über Git. Schadet nicht, also aktivieren.
|
|
||||||
lfs.enable = true;
|
|
||||||
|
|
||||||
# Wo Forgejo seine Repositories auf dem Dateisystem speichert.
|
|
||||||
# Standardmäßig /var/lib/forgejo/repositories – das ist gut so.
|
|
||||||
# repositoryRoot = "/var/lib/forgejo/repositories"; # optional überschreiben
|
|
||||||
|
|
||||||
settings = {
|
|
||||||
|
|
||||||
server = {
|
|
||||||
DOMAIN = "git.nikolai-linschmann.de";
|
|
||||||
# ROOT_URL muss gesetzt sein, sonst erscheint der Port in allen URLs im Web-UI.
|
|
||||||
# srv.DOMAIN referenziert den Wert der DOMAIN-Option direkt oben.
|
|
||||||
ROOT_URL = "https://${srv.DOMAIN}/";
|
|
||||||
HTTP_PORT = 3000; # Interner Port, nach außen kommt nur Nginx
|
|
||||||
};
|
|
||||||
|
|
||||||
service = {
|
|
||||||
# Registrierung deaktivieren – du bist der einzige Nutzer.
|
|
||||||
# Nach dem ersten Start temporär auf false setzen (siehe Schritt 4),
|
|
||||||
# dann wieder auf true.
|
|
||||||
DISABLE_REGISTRATION = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Sicherheit: Sessions und Tokens laufen nach 7 Tagen ab.
|
|
||||||
security = {
|
|
||||||
LOGIN_REMEMBER_DAYS = 7;
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# ============================================================
|
|
||||||
# NGINX REVERSE PROXY
|
|
||||||
# ============================================================
|
|
||||||
# Nginx nimmt HTTPS-Anfragen von außen entgegen und leitet
|
|
||||||
# sie intern an Forgejo auf Port 3000 weiter.
|
|
||||||
|
|
||||||
services.nginx.virtualHosts.${srv.DOMAIN} = {
|
|
||||||
forceSSL = true; # HTTP → HTTPS Redirect
|
|
||||||
enableACME = true; # Let's Encrypt Zertifikat automatisch holen und erneuern
|
|
||||||
|
|
||||||
extraConfig = ''
|
|
||||||
# Erlaubt große Uploads (z.B. Git-Pushes mit vielen Dateien).
|
|
||||||
# 512M ist ein guter Standardwert für eine persönliche Instanz.
|
|
||||||
client_max_body_size 512M;
|
|
||||||
'';
|
|
||||||
|
|
||||||
locations."/" = {
|
|
||||||
# srv.HTTP_PORT ist 3000 – toString wandelt die Zahl in einen String um.
|
|
||||||
proxyPass = "http://127.0.0.1:${toString srv.HTTP_PORT}";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# ============================================================
|
|
||||||
# SSH-INTEGRATION
|
|
||||||
# ============================================================
|
|
||||||
# Damit "git clone git@git.nikolai-linschmann.de:user/repo.git" funktioniert.
|
|
||||||
# Forgejo braucht zu wissen auf welchem Port OpenSSH läuft.
|
|
||||||
|
|
||||||
services.forgejo.settings.server.SSH_PORT =
|
|
||||||
lib.head config.services.openssh.ports;
|
|
||||||
# lib.head nimmt das erste Element der Liste der SSH-Ports (normalerweise 22).
|
|
||||||
|
|
||||||
# ============================================================
|
|
||||||
# FIREWALL
|
|
||||||
# ============================================================
|
|
||||||
# Port 80 (HTTP) und 443 (HTTPS) müssen offen sein.
|
|
||||||
# Falls das schon zentral in configuration.nix steht, diesen Block weglassen.
|
|
||||||
|
|
||||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
|
||||||
}
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
git
|
git
|
||||||
htop
|
htop
|
||||||
ncdu
|
ncdu
|
||||||
nginx
|
|
||||||
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,247 +0,0 @@
|
||||||
# ==============================================================================
|
|
||||||
# PROJECT SKELETON — NixOS Service Module
|
|
||||||
# ==============================================================================
|
|
||||||
#
|
|
||||||
# USAGE:
|
|
||||||
# 1. Copy this file into your project repo, e.g. ~/projects/my-project/my-project.nix
|
|
||||||
# 2. Replace every occurrence of:
|
|
||||||
# MY_PROJECT → your project name in camelCase (e.g. myRssReader)
|
|
||||||
# my-project → your project name in kebab-case (e.g. my-rss-reader)
|
|
||||||
# my-project.example.com → your actual domain
|
|
||||||
# 127.0.0.1:3000 → the address your app listens on internally
|
|
||||||
# 3. In /etc/nixos/configuration.nix, add:
|
|
||||||
# imports = [ /path/to/my-project.nix ];
|
|
||||||
# services.MY_PROJECT.enable = true;
|
|
||||||
#
|
|
||||||
# ASSUMPTIONS:
|
|
||||||
# - Nginx global settings (recommendedTlsSettings etc.) and ACME email are
|
|
||||||
# configured centrally in configuration.nix (see bottom of this file).
|
|
||||||
# - Your app runs as a systemd service on a local port (reverse proxy setup).
|
|
||||||
# - You want HTTPS via Let's Encrypt.
|
|
||||||
#
|
|
||||||
# ==============================================================================
|
|
||||||
|
|
||||||
{ config, pkgs, lib, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
# The internal port your application listens on.
|
|
||||||
# Nginx will forward public traffic here.
|
|
||||||
appPort = 3000;
|
|
||||||
|
|
||||||
# Shorthand so you can reference the merged config of this module cleanly.
|
|
||||||
cfg = config.services.MY_PROJECT;
|
|
||||||
|
|
||||||
in
|
|
||||||
{
|
|
||||||
# ============================================================================
|
|
||||||
# OPTIONS
|
|
||||||
# Define the knobs that other files (or configuration.nix) can turn.
|
|
||||||
# Nothing in `config` below runs until `enable` is set to true.
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
options.services.MY_PROJECT = {
|
|
||||||
|
|
||||||
enable = lib.mkEnableOption "MY_PROJECT service";
|
|
||||||
# Adds a boolean option `services.MY_PROJECT.enable` that defaults to false.
|
|
||||||
# Set it to true in configuration.nix to activate this module.
|
|
||||||
|
|
||||||
domain = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "my-project.example.com";
|
|
||||||
description = "The public domain name Nginx will serve and ACME will certify.";
|
|
||||||
};
|
|
||||||
|
|
||||||
port = lib.mkOption {
|
|
||||||
type = lib.types.port;
|
|
||||||
default = appPort;
|
|
||||||
description = "Internal port the application process listens on.";
|
|
||||||
};
|
|
||||||
|
|
||||||
dataDir = lib.mkOption {
|
|
||||||
type = lib.types.path;
|
|
||||||
default = "/var/lib/my-project";
|
|
||||||
description = "Directory for persistent application data (database, uploads, etc.).";
|
|
||||||
};
|
|
||||||
|
|
||||||
# Optional: expose an environment file path for secrets.
|
|
||||||
# The file should contain KEY=VALUE pairs and never be committed to git.
|
|
||||||
# Example content:
|
|
||||||
# DATABASE_URL=postgres://user:password@localhost/mydb
|
|
||||||
# SECRET_KEY=supersecret
|
|
||||||
environmentFile = lib.mkOption {
|
|
||||||
type = lib.types.nullOr lib.types.path;
|
|
||||||
default = null;
|
|
||||||
description = ''
|
|
||||||
Path to a file containing secret environment variables.
|
|
||||||
This file is read by systemd at runtime and never stored in the Nix store.
|
|
||||||
Example: /run/secrets/my-project.env
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
# ============================================================================
|
|
||||||
# CONFIG
|
|
||||||
# Everything below only takes effect when `services.MY_PROJECT.enable = true`.
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------
|
|
||||||
# Systemd Service
|
|
||||||
# Runs your application as a background process.
|
|
||||||
# --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
systemd.services.my-project = {
|
|
||||||
description = "MY_PROJECT application service";
|
|
||||||
|
|
||||||
# Start after the network and (if used) PostgreSQL are ready.
|
|
||||||
after = [ "network.target" "postgresql.service" ];
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
|
|
||||||
serviceConfig = {
|
|
||||||
# --- Replace this with your actual start command ---
|
|
||||||
# Examples:
|
|
||||||
# Node.js: "${pkgs.nodejs}/bin/node ${cfg.dataDir}/server.js"
|
|
||||||
# Python: "${pkgs.python3}/bin/python ${cfg.dataDir}/app.py"
|
|
||||||
# Binary: "${pkgs.my-package}/bin/my-binary"
|
|
||||||
ExecStart = "${pkgs.nodejs}/bin/node ${cfg.dataDir}/server.js";
|
|
||||||
|
|
||||||
# Working directory for the process.
|
|
||||||
WorkingDirectory = cfg.dataDir;
|
|
||||||
|
|
||||||
# DynamicUser: systemd creates an unprivileged user automatically.
|
|
||||||
# The user has no fixed UID and cannot log in. Good for most services.
|
|
||||||
# Set to false if you need a persistent user (e.g. for file ownership).
|
|
||||||
DynamicUser = true;
|
|
||||||
|
|
||||||
# Give the dynamic user write access to the data directory.
|
|
||||||
StateDirectory = "my-project";
|
|
||||||
StateDirectoryMode = "0750";
|
|
||||||
|
|
||||||
# Load secrets from a file at runtime (optional).
|
|
||||||
# The contents are injected as environment variables.
|
|
||||||
EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile;
|
|
||||||
|
|
||||||
# Hardening — remove lines you don't need, but keep as many as possible.
|
|
||||||
NoNewPrivileges = true;
|
|
||||||
PrivateTmp = true; # /tmp is isolated from other services
|
|
||||||
ProtectSystem = "strict";
|
|
||||||
ProtectHome = true;
|
|
||||||
RestrictSUIDSGID = true;
|
|
||||||
LockPersonality = true;
|
|
||||||
RestrictNamespaces = true;
|
|
||||||
|
|
||||||
# Restart automatically if the process crashes.
|
|
||||||
Restart = "on-failure";
|
|
||||||
RestartSec = "5s";
|
|
||||||
};
|
|
||||||
|
|
||||||
# Environment variables that are safe to be in the Nix store.
|
|
||||||
# For secrets, use environmentFile above instead.
|
|
||||||
environment = {
|
|
||||||
NODE_ENV = "production";
|
|
||||||
PORT = toString cfg.port;
|
|
||||||
DATA_DIR = cfg.dataDir;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------
|
|
||||||
# Nginx Virtual Host
|
|
||||||
# Terminates TLS and proxies requests to the local application port.
|
|
||||||
# --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
services.nginx = {
|
|
||||||
# Nginx is enabled automatically when virtualHosts is non-empty,
|
|
||||||
# but being explicit is clearer.
|
|
||||||
enable = true;
|
|
||||||
|
|
||||||
virtualHosts.${cfg.domain} = {
|
|
||||||
|
|
||||||
# Redirect all plain HTTP to HTTPS.
|
|
||||||
forceSSL = true;
|
|
||||||
|
|
||||||
# Let NixOS manage the Let's Encrypt certificate automatically.
|
|
||||||
# Renewal is handled by a systemd timer — no manual cron needed.
|
|
||||||
# Requires: security.acme.acceptTerms = true and defaults.email set
|
|
||||||
# in your central configuration.nix.
|
|
||||||
enableACME = true;
|
|
||||||
|
|
||||||
# --- Main reverse proxy location ---
|
|
||||||
locations."/" = {
|
|
||||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
|
||||||
|
|
||||||
# Needed for apps that use WebSockets (e.g. live reload, chat).
|
|
||||||
# Remove these two lines if your app does not use WebSockets.
|
|
||||||
proxyWebsockets = true;
|
|
||||||
extraConfig = ''
|
|
||||||
proxy_read_timeout 60s;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# --- Optional: serve static files directly from Nginx ---
|
|
||||||
# Uncomment and adjust if your app has a public assets directory.
|
|
||||||
# Serving static files from Nginx is faster than going through Node/Python.
|
|
||||||
#
|
|
||||||
# locations."/static/" = {
|
|
||||||
# alias = "${cfg.dataDir}/static/";
|
|
||||||
# extraConfig = ''
|
|
||||||
# expires 30d;
|
|
||||||
# add_header Cache-Control "public, immutable";
|
|
||||||
# '';
|
|
||||||
# };
|
|
||||||
|
|
||||||
# --- Optional: block access to sensitive paths ---
|
|
||||||
# locations."~ /\\." = {
|
|
||||||
# extraConfig = "deny all;";
|
|
||||||
# };
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------
|
|
||||||
# PostgreSQL Database (optional)
|
|
||||||
# Uncomment this block if your project needs a database.
|
|
||||||
# --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# services.postgresql = {
|
|
||||||
# enable = true;
|
|
||||||
#
|
|
||||||
# # Creates the database and user if they don't exist yet.
|
|
||||||
# ensureDatabases = [ "my-project" ];
|
|
||||||
# ensureUsers = [{
|
|
||||||
# name = "my-project";
|
|
||||||
# ensureDBOwnership = true;
|
|
||||||
# }];
|
|
||||||
# };
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------
|
|
||||||
# Firewall
|
|
||||||
# Ports 80 and 443 must be open for Nginx and Let's Encrypt to work.
|
|
||||||
# If these are already opened in configuration.nix, remove this block.
|
|
||||||
# --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
# ============================================================================
|
|
||||||
# CENTRAL CONFIGURATION.NIX REQUIREMENTS
|
|
||||||
#
|
|
||||||
# Make sure these are set somewhere in your configuration.nix (not here,
|
|
||||||
# so they are shared across all project modules without duplication):
|
|
||||||
#
|
|
||||||
# services.nginx = {
|
|
||||||
# recommendedGzipSettings = true;
|
|
||||||
# recommendedOptimisation = true;
|
|
||||||
# recommendedTlsSettings = true;
|
|
||||||
# recommendedProxySettings = true;
|
|
||||||
# };
|
|
||||||
#
|
|
||||||
# security.acme = {
|
|
||||||
# acceptTerms = true;
|
|
||||||
# defaults.email = "your@email.com";
|
|
||||||
# };
|
|
||||||
#
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue