Initial NixOS infra flake skeleton

This commit is contained in:
Eli Fadi 2026-03-03 11:21:32 +01:00
commit 9383d615d7
9 changed files with 267 additions and 0 deletions

53
flake.nix Normal file
View file

@ -0,0 +1,53 @@
{
description = "Flowback infra (NixOS): Nextcloud + Forgejo, staging + production";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
# Optional, but strongly recommended for secrets:
sops-nix.url = "github:Mic92/sops-nix";
sops-nix.inputs.nixpkgs.follows = "nixpkgs";
};
outputs = { self, nixpkgs, sops-nix, ... }:
let
mkHost = { name, system, modules }:
nixpkgs.lib.nixosSystem {
inherit system;
modules =
modules ++ [
sops-nix.nixosModules.sops
];
specialArgs = { inherit name; };
};
in
{
# Staging host (x86_64 for VM/cloud)
nixosConfigurations.staging = mkHost {
name = "staging";
system = "x86_64-linux";
modules = [
./hosts/staging/configuration.nix
];
};
# Production host (x86_64 for VM/cloud)
nixosConfigurations.production = mkHost {
name = "production";
system = "x86_64-linux";
modules = [
./hosts/production/configuration.nix
];
};
# Raspberry Pi example (aarch64) — use when youre ready
# nixosConfigurations.rpi-staging = mkHost {
# name = "rpi-staging";
# system = "aarch64-linux";
# modules = [
# ./hosts/staging/configuration.nix
# ./hosts/staging/rpi-hardware.nix
# ];
# };
};
}

View file

@ -0,0 +1,33 @@
{ config, pkgs, lib, name, ... }:
{
imports = [
../../modules/common.nix
../../modules/sops.nix
../../modules/nextcloud.nix
../../modules/forgejo.nix
];
networking.hostName = name;
# Prod: open ports for web
networking.firewall.allowedTCPPorts = [ 80 443 22 ];
services.flowback = {
nextcloudHost = "cloud.example.com";
forgejoHost = "git.example.com";
};
# Production should enforce stronger auth; you can refine later.
users.users.elifa = {
isNormalUser = true;
extraGroups = [ "wheel" ];
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGI1L2SZzAfxkdHPsgJe0cx9s0owlMPyS6LnAURzXyad eli@wsl"
];
};
security.sudo.wheelNeedsPassword = true;
system.stateVersion = "25.11";
}

View file

@ -0,0 +1,34 @@
{ config, pkgs, lib, name, ... }:
{
imports = [
../../modules/common.nix
../../modules/sops.nix
../../modules/nextcloud.nix
../../modules/forgejo.nix
];
networking.hostName = name;
# Staging: open ports for web
networking.firewall.allowedTCPPorts = [ 80 443 22 ];
# Put placeholders for domains now; you can change later
services.flowback = {
nextcloudHost = "cloud-staging.example.com";
forgejoHost = "git-staging.example.com";
};
# Minimal user (replace with your SSH key)
users.users.elifa = {
isNormalUser = true;
extraGroups = [ "wheel" ];
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGI1L2SZzAfxkdHPsgJe0cx9s0owlMPyS6LnAURzXyad eli@wsl"
];
};
security.sudo.wheelNeedsPassword = false;
system.stateVersion = "25.11";
}

31
modules/common.nix Normal file
View file

@ -0,0 +1,31 @@
{ config, pkgs, lib, ... }:
{
# Basic sane defaults
time.timeZone = "Europe/Stockholm";
# SSH access (youll tweak users later)
services.openssh.enable = true;
services.openssh.settings = {
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
PermitRootLogin = "no";
};
# Helpful tools on the server
environment.systemPackages = with pkgs; [
git
curl
jq
vim
];
# Firewall on by default
networking.firewall.enable = true;
# Nix settings (good defaults)
nix.settings = {
experimental-features = [ "nix-command" "flakes" ];
auto-optimise-store = true;
};
}

View file

@ -0,0 +1,16 @@
{ lib, ... }:
let
inherit (lib) mkOption types;
in
{
options.services.flowback = {
nextcloudHost = mkOption {
type = types.str;
description = "Hostname for Nextcloud";
};
forgejoHost = mkOption {
type = types.str;
description = "Hostname for Forgejo";
};
};
}

36
modules/forgejo.nix Normal file
View file

@ -0,0 +1,36 @@
{ config, pkgs, lib, ... }:
{
imports = [ ./flowback-options.nix ];
services.nginx.enable = true;
security.acme.acceptTerms = true;
security.acme.defaults.email = "me@example.com";
services.forgejo = {
enable = true;
settings = {
server = {
DOMAIN = config.services.flowback.forgejoHost;
ROOT_URL = "https://${config.services.flowback.forgejoHost}/";
HTTP_PORT = 3000;
};
service = {
DISABLE_REGISTRATION = true;
};
};
# Database defaults are okay to start; you can move to Postgres if desired
};
services.nginx.virtualHosts.${config.services.flowback.forgejoHost} = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:3000";
proxyWebsockets = true;
};
};
networking.firewall.allowedTCPPorts = [ 22 ];
}

38
modules/nextcloud.nix Normal file
View file

@ -0,0 +1,38 @@
{ config, pkgs, lib, ... }:
{
imports = [ ./flowback-options.nix ];
# Enable nginx + ACME (TLS). Works when DNS points correctly.
services.nginx.enable = true;
security.acme.acceptTerms = true;
# I will change this email later
security.acme.defaults.email = "me@example.com";
services.nextcloud = {
enable = true;
hostName = config.services.flowback.nextcloudHost;
https = true;
# Performance / reliability
configureRedis = true;
# DB locally (Postgres) — production-ready baseline
database.createLocally = true;
# Admin bootstrap secret will be wired via sops later.
# For now, placeholder: youll set adminpassFile via sops secret.
config = {
adminuser = "admin";
adminpassFile = "/var/lib/sops-nix/nextcloud-adminpass";
dbtype = "pgsql";
dbpassFile = "/var/lib/sops-nix/nextcloud-dbpass";
};
};
services.nginx.virtualHosts.${config.services.flowback.nextcloudHost} = {
forceSSL = true;
enableACME = true;
};
}

15
modules/sops.nix Normal file
View file

@ -0,0 +1,15 @@
{ config, lib, ... }:
{
# sops-nix reads secrets from YAML files in ./secrets
# You will create these later.
sops.defaultSopsFile = ../secrets/secrets.yaml;
# Where the age key lives on target machines
sops.age.keyFile = "/var/lib/sops-nix/key.txt";
# Good to have a dedicated secrets mount/dir
systemd.tmpfiles.rules = [
"d /var/lib/sops-nix 0700 root root - -"
];
}

11
secrets/README.md Normal file
View file

@ -0,0 +1,11 @@
Secrets are managed using sops + age.
This repo expects an encrypted file:
secrets/secrets.yaml
It should contain:
- nextcloud-adminpass
- nextcloud-dbpass
On a target server you also need:
/var/lib/sops-nix/key.txt (age private key)