nix: add vps setup

This commit is contained in:
Oleksandr Smirnov 2026-01-14 21:45:55 +02:00
parent 028a52d9ff
commit 4240620b6b
No known key found for this signature in database
13 changed files with 498 additions and 0 deletions

130
nix/flake.lock generated Normal file
View file

@ -0,0 +1,130 @@
{
"nodes": {
"agenix": {
"inputs": {
"darwin": "darwin",
"home-manager": "home-manager",
"nixpkgs": [
"nixpkgs"
],
"systems": "systems"
},
"locked": {
"lastModified": 1762618334,
"narHash": "sha256-wyT7Pl6tMFbFrs8Lk/TlEs81N6L+VSybPfiIgzU8lbQ=",
"owner": "ryantm",
"repo": "agenix",
"rev": "fcdea223397448d35d9b31f798479227e80183f6",
"type": "github"
},
"original": {
"owner": "ryantm",
"repo": "agenix",
"type": "github"
}
},
"darwin": {
"inputs": {
"nixpkgs": [
"agenix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1744478979,
"narHash": "sha256-dyN+teG9G82G+m+PX/aSAagkC+vUv0SgUw3XkPhQodQ=",
"owner": "lnl7",
"repo": "nix-darwin",
"rev": "43975d782b418ebf4969e9ccba82466728c2851b",
"type": "github"
},
"original": {
"owner": "lnl7",
"ref": "master",
"repo": "nix-darwin",
"type": "github"
}
},
"disko": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1766150702,
"narHash": "sha256-P0kM+5o+DKnB6raXgFEk3azw8Wqg5FL6wyl9jD+G5a4=",
"owner": "nix-community",
"repo": "disko",
"rev": "916506443ecd0d0b4a0f4cf9d40a3c22ce39b378",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "disko",
"type": "github"
}
},
"home-manager": {
"inputs": {
"nixpkgs": [
"agenix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1745494811,
"narHash": "sha256-YZCh2o9Ua1n9uCvrvi5pRxtuVNml8X2a03qIFfRKpFs=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "abfad3d2958c9e6300a883bd443512c55dfeb1be",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "home-manager",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1767313136,
"narHash": "sha256-16KkgfdYqjaeRGBaYsNrhPRRENs0qzkQVUooNHtoy2w=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "ac62194c3917d5f474c1a844b6fd6da2db95077d",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-25.05",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"agenix": "agenix",
"disko": "disko",
"nixpkgs": "nixpkgs"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

33
nix/flake.nix Normal file
View file

@ -0,0 +1,33 @@
{
description = "my nix";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";
agenix = {
url = "github:ryantm/agenix";
inputs.nixpkgs.follows = "nixpkgs";
};
disko = {
url = "github:nix-community/disko";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs =
{
self,
nixpkgs,
agenix,
disko,
...
}@inputs:
{
nixosConfigurations."thought" = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
./hosts/thought
agenix.nixosModules.default
disko.nixosModules.disko
];
};
};
}

View file

@ -0,0 +1,74 @@
{ pkgs, ... }:
{
imports = [
./disko-config.nix
./hardware-configuration.nix
];
system.stateVersion = "24.05";
swapDevices = [
{
device = "/swapfile";
size = 2048; # MB
}
];
boot.loader.grub = {
efiSupport = true;
efiInstallAsRemovable = true;
};
time.timeZone = "Europe/Kyiv";
i18n.defaultLocale = "en_US.UTF-8";
networking = {
hostName = "vps";
useDHCP = true;
# Interface names will be auto-detected in hardware-configuration.nix
# Using generic DHCP setting
interfaces = { };
firewall = {
enable = true;
allowedTCPPorts = [
80
443
];
};
};
environment.systemPackages = with pkgs; [
neovim
git
htop
tmux
];
age.identityPaths = [ "/keys.txt" ]; # TODO: i dont like that i overwrites literally everything
services = {
caddy.enable = true;
openssh = {
enable = true;
settings = {
PasswordAuthentication = false;
PermitRootLogin = "no";
};
};
};
nix = {
gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 30d";
};
settings = {
auto-optimise-store = true;
experimental-features = [
"nix-command"
"flakes"
];
};
};
}

View file

@ -0,0 +1,11 @@
{ ... }:
{
imports = [
./digitalocean.nix
./configuration.nix
./hardware-configuration.nix
../../users/q.nix
../../modules/forgejo.nix
];
}

View file

@ -0,0 +1,70 @@
{ lib, modulesPath, ... }:
{
imports = [
"${modulesPath}/virtualisation/digital-ocean-config.nix"
];
# do not use DHCP, as DigitalOcean provisions IPs using cloud-init
networking.useDHCP = lib.mkForce false;
# Disables all modules that do not work with NixOS
services.cloud-init = {
enable = true;
network.enable = true;
settings = {
datasource_list = [
"ConfigDrive"
"Digitalocean"
];
datasource.ConfigDrive = { };
datasource.Digitalocean = { };
# Based on https://github.com/canonical/cloud-init/blob/main/config/cloud.cfg.tmpl
cloud_init_modules = [
"seed_random"
"bootcmd"
"write_files"
"growpart"
"resizefs"
"set_hostname"
"update_hostname"
# Not support on NixOS
#"update_etc_hosts"
# throws error
#"users-groups"
# tries to edit /etc/ssh/sshd_config
#"ssh"
"set_password"
];
cloud_config_modules = [
"ssh-import-id"
"keyboard"
# doesn't work with nixos
#"locale"
"runcmd"
"disable_ec2_metadata"
];
## The modules that run in the 'final' stage
cloud_final_modules = [
"write_files_deferred"
"puppet"
"chef"
"ansible"
"mcollective"
"salt_minion"
"reset_rmc"
# install dotty agent fails
#"scripts_vendor"
"scripts_per_once"
"scripts_per_boot"
# /var/lib/cloud/scripts/per-instance/machine_id.sh has broken shebang
#"scripts_per_instance"
"scripts_user"
"ssh_authkey_fingerprints"
"keys_to_console"
"install_hotplug"
"phone_home"
"final_message"
];
};
};
}

View file

@ -0,0 +1,55 @@
{ lib, ... }:
{
disko.devices = {
disk.disk1 = {
device = lib.mkDefault "/dev/vda";
type = "disk";
content = {
type = "gpt";
partitions = {
boot = {
name = "boot";
size = "1M";
type = "EF02";
};
esp = {
name = "ESP";
size = "500M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
};
root = {
name = "root";
size = "100%";
content = {
type = "lvm_pv";
vg = "pool";
};
};
};
};
};
lvm_vg = {
pool = {
type = "lvm_vg";
lvs = {
root = {
size = "100%FREE";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
mountOptions = [
"defaults"
];
};
};
};
};
};
};
}

View file

@ -0,0 +1,25 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:
{
imports =
[ (modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "virtio_blk" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.ens3.useDHCP = lib.mkDefault true;
# networking.interfaces.ens4.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}

58
nix/modules/forgejo.nix Normal file
View file

@ -0,0 +1,58 @@
{
config,
pkgs,
lib,
...
}:
let
domain = "git.olexsmir.xyz";
in
{
services.caddy.virtualHosts.${domain}.extraConfig = ''
reverse_proxy http://localhost:3001
'';
services.forgejo = {
enable = true;
database.type = "sqlite3";
settings = {
server = {
DOMAIN = domain;
ROOT_URL = "https://${domain}/";
HTTP_PORT = 3001;
LANDING_PAGE = "explore";
};
DEFAULT.APP_NAME = "my git";
repository.DISABLE_STARS = true;
service.DISABLE_REGISTRATION = true;
ui.DEFAULT_THEME = "forgejo-dark";
actions = {
ENABLED = true;
DEFAULT_ACTIONS_URL = "https://${domain}";
};
};
};
# automatically setup user
age.secrets.forgejo-admin-password = {
file = ../secrets/forgejo-admin-password.age;
owner = "forgejo";
group = "forgejo";
};
systemd.services.forgejo.preStart =
let
adminCmd = "${lib.getExe config.services.forgejo.package} admin user";
passwordFile = config.age.secrets.forgejo-admin-password.path;
user = "olexsmir";
in
''
${adminCmd} create --admin --email "root@localhost" --username ${user} --password "$(tr -d '\n' < ${passwordFile})" || true
## uncomment this line to change an admin user which was already created
# ${adminCmd} change-password --username ${user} --password "$(tr -d '\n' < ${passwordFile})" || true
'';
# TODO: setup workers
# ideally it would get a token automatically
}

Binary file not shown.

View file

@ -0,0 +1,7 @@
age-encryption.org/v1
-> ssh-ed25519 jgjvUw UGkfiK9jMSVJHUSWbw/E1hgLNQWHD7vR0KWQwwolyRY
oRp/4aqLuMSe5htBpMMzNLDD/5t/GL67GydCZYckQgM
-> X25519 iaKPWzhHO9id5G8g2RoDoxKCmdjqTt9HvUjjEUUQOno
lTZp1EYtgdCYs8qKA1tipzKdcD5cMrunhfWzqpOfS/s
--- JSzZdVhBrsFtBjN36DqxkKg0c4RjvThtTYJXpE5TbTo
TÎ}‰gz¦µÂ“N7)_Lé—w)dYBäŸEÔ÷£n+ÿœgwõêê¤d±ªº„üß)¶±G5<47>¾ãjHÂÜt¿pÀ

View file

@ -0,0 +1,7 @@
age-encryption.org/v1
-> ssh-ed25519 jgjvUw Yy4VmBRoL5acIbY+GMmg5qW9iTp9U/XZSvx12r3SzRU
rNNYDN0ikwrSJf8kKi0uLczMY39rg0Xi3MSvR9fAzYU
-> X25519 t9640/amrr9kdgjY9ALE0n6yoaqMGTCjjk0OxPmHwwM
x6nm6fXvrrRngMJVY8oGh8QJU0K5TBkl7S+v5E3k8iw
--- kM18cW1nk37CnZlFmdS0XAuCt6gHzazZ83X9iNuzb5w
ôžàXöOÈb^µÇïìYÌe]Ýy³ÊG-„•d¹<64>ùб

13
nix/secrets/secrets.nix Normal file
View file

@ -0,0 +1,13 @@
let
laptop = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLLJdkVYKZgsayw+sHanKPKZbI0RMS2CakqBCEi5Trz";
infra = "age1k4e6mm0whyjzfaqlhahu2pst4vxvzul53xs3ff0tk8uty459zgzqk3965k";
allKeys = [
laptop
infra
];
in
{
"forgejo-admin-password.age".publicKeys = allKeys;
"forgejo-runner-token.age".publicKeys = allKeys;
"q-password.age".publicKeys = allKeys;
}

15
nix/users/q.nix Normal file
View file

@ -0,0 +1,15 @@
{ config, ... }:
{
age.secrets.q-password.file = ../secrets/q-password.age;
users.users.q = {
isNormalUser = true;
extraGroups = [ "wheel" ];
# initialPassword = "qwerty123";
hashedPasswordFile = config.age.secrets.q-password.path;
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLLJdkVYKZgsayw+sHanKPKZbI0RMS2CakqBCEi5Trz" # laptop
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINeXccmMQ9jfLG2Z8CITaZZ+pUgYVNVYDFtmdkBHd3xk u0_a930@localhost" # phone
];
};
}