Initial NixOS infra flake skeleton
This commit is contained in:
commit
9383d615d7
9 changed files with 267 additions and 0 deletions
53
flake.nix
Normal file
53
flake.nix
Normal 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 you’re ready
|
||||
# nixosConfigurations.rpi-staging = mkHost {
|
||||
# name = "rpi-staging";
|
||||
# system = "aarch64-linux";
|
||||
# modules = [
|
||||
# ./hosts/staging/configuration.nix
|
||||
# ./hosts/staging/rpi-hardware.nix
|
||||
# ];
|
||||
# };
|
||||
};
|
||||
}
|
||||
33
hosts/production/configuration.nix
Normal file
33
hosts/production/configuration.nix
Normal 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";
|
||||
}
|
||||
34
hosts/staging/configuration.nix
Normal file
34
hosts/staging/configuration.nix
Normal 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
31
modules/common.nix
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# Basic sane defaults
|
||||
time.timeZone = "Europe/Stockholm";
|
||||
|
||||
# SSH access (you’ll 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;
|
||||
};
|
||||
}
|
||||
16
modules/flowback-options.nix
Normal file
16
modules/flowback-options.nix
Normal 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
36
modules/forgejo.nix
Normal 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
38
modules/nextcloud.nix
Normal 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: you’ll 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
15
modules/sops.nix
Normal 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
11
secrets/README.md
Normal 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)
|
||||
Loading…
Add table
Add a link
Reference in a new issue