mirror of
https://github.com/acaloiaro/sfos
synced 2026-07-21 02:09:53 +00:00
Wip: terraform stuff done, but nixos-anywhere stil in progress
This commit is contained in:
parent
51b9b887bb
commit
8ac707da3b
30 changed files with 2478 additions and 9 deletions
1
.envrc
1
.envrc
|
|
@ -13,4 +13,3 @@ if ! use flake . --impure
|
|||
then
|
||||
echo "devenv could not be built. The devenv environment was not loaded." >&2
|
||||
fi
|
||||
|
||||
|
|
|
|||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -2,4 +2,5 @@
|
|||
**/*.devenv
|
||||
**/*.img
|
||||
**/*.direnv
|
||||
**/*.terraform*
|
||||
.pre-commit-config.yaml
|
||||
|
|
|
|||
33
bootstrap/common/nix.nix
Normal file
33
bootstrap/common/nix.nix
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
{pkgs, ...}: {
|
||||
nixpkgs = {
|
||||
config = {
|
||||
allowUnfree = true;
|
||||
};
|
||||
};
|
||||
|
||||
nix = {
|
||||
package = pkgs.nix;
|
||||
|
||||
gc = {
|
||||
automatic = true;
|
||||
dates = "weekly";
|
||||
options = "--delete-older-than 14d";
|
||||
};
|
||||
|
||||
settings = {
|
||||
trusted-users = [
|
||||
"@wheel"
|
||||
];
|
||||
|
||||
experimental-features = [
|
||||
"flakes"
|
||||
"nix-command"
|
||||
];
|
||||
|
||||
trusted-public-keys = [
|
||||
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
|
||||
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
106
bootstrap/compute_providers/hetzner/main.tf
Normal file
106
bootstrap/compute_providers/hetzner/main.tf
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
terraform {
|
||||
required_providers {
|
||||
hcloud = {
|
||||
source = "hetznercloud/hcloud"
|
||||
version = "1.49.1"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
provider "hcloud" {
|
||||
token = var.compute_provider_access_token
|
||||
}
|
||||
|
||||
resource "hcloud_ssh_key" "admin" {
|
||||
name = "sfos admin user"
|
||||
public_key = var.admin_ssh_public_key
|
||||
}
|
||||
|
||||
#####################################################################################################################
|
||||
# Instances
|
||||
#####################################################################################################################
|
||||
|
||||
locals {
|
||||
# These are the private IP addresses that are assigned to each node
|
||||
# We start at the buttom of the cidr block + 2 because 0 is not routable and 1 is reserved; hence "i + 2" below
|
||||
node_private_ips = {
|
||||
value = [for i in range(var.node_count) : "${cidrhost(var.internal_cidr_block, i + 2)}"]
|
||||
}
|
||||
}
|
||||
|
||||
resource "hcloud_server" "nodes" {
|
||||
count = var.node_count
|
||||
name = "sfos-${count.index}"
|
||||
image = "ubuntu-22.04" # This is the _initial_ OS installed on the nodes. NixOS is installed over this later
|
||||
server_type = var.compute_provider_node_type
|
||||
location = var.compute_provider_region
|
||||
ssh_keys = [hcloud_ssh_key.admin.id]
|
||||
labels = {
|
||||
"sfos" : true
|
||||
}
|
||||
user_data = data.template_file.add_to_tailnet.rendered
|
||||
firewall_ids = [hcloud_firewall.allow_ssh.id]
|
||||
}
|
||||
|
||||
|
||||
data "template_file" "add_to_tailnet" {
|
||||
template = file("config/add_to_tailnet.tpl")
|
||||
vars = {
|
||||
tailscale_auth_key = var.tailscale_auth_key
|
||||
admin_ssh_public_key = var.admin_ssh_public_key
|
||||
}
|
||||
}
|
||||
|
||||
#####################################################################################################################
|
||||
# Network
|
||||
#####################################################################################################################
|
||||
|
||||
# This network is used solely for load balancing support, since HZ load balancers need to operate on a private subnet
|
||||
resource "hcloud_network" "sfos_private" {
|
||||
name = "cluster-private"
|
||||
ip_range = var.internal_cidr_block
|
||||
}
|
||||
|
||||
resource "hcloud_server_network" "sfos_network" {
|
||||
count = var.node_count
|
||||
server_id = hcloud_server.nodes[count.index].id
|
||||
subnet_id = hcloud_network_subnet.private_subnet.id
|
||||
ip = local.node_private_ips.value[count.index]
|
||||
}
|
||||
|
||||
resource "hcloud_network_subnet" "private_subnet" {
|
||||
network_id = hcloud_network.sfos_private.id
|
||||
type = "cloud"
|
||||
network_zone = "us-east"
|
||||
ip_range = var.internal_cidr_block
|
||||
}
|
||||
|
||||
resource "hcloud_firewall" "allow_ssh" {
|
||||
name = "Allow SSH"
|
||||
|
||||
rule {
|
||||
direction = "in"
|
||||
protocol = "tcp"
|
||||
port = "22"
|
||||
source_ips = [
|
||||
"0.0.0.0/0",
|
||||
"::/0"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
#####################################################################################################################
|
||||
# Storage
|
||||
#####################################################################################################################
|
||||
|
||||
# This volume is reserved for the general purpose storage for any application
|
||||
# resource "hcloud_volume" "gp-storage" {
|
||||
# name = "gp-storage"
|
||||
# size = 10
|
||||
# location = var.compute_provider_region
|
||||
# format = "xfs"
|
||||
# delete_protection = true
|
||||
# }
|
||||
|
||||
|
||||
1
bootstrap/compute_providers/hetzner/variables.tf
Symbolic link
1
bootstrap/compute_providers/hetzner/variables.tf
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
/home/adriano/git/sfos/bootstrap/variables.tf
|
||||
41
bootstrap/compute_providers/linode/linode.tf
Normal file
41
bootstrap/compute_providers/linode/linode.tf
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
terraform {
|
||||
required_providers {
|
||||
linode = {
|
||||
source = "linode/linode"
|
||||
version = "2.31.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "linode" {
|
||||
token = var.compute_provider_access_token
|
||||
}
|
||||
|
||||
resource "linode_sshkey" "sfos_admin" {
|
||||
label = "sfos-admin"
|
||||
ssh_key = var.admin_ssh_public_key
|
||||
}
|
||||
|
||||
#####################################################################################################################
|
||||
# Instances
|
||||
#####################################################################################################################
|
||||
|
||||
locals {
|
||||
# These are the private IP addresses that are assigned to each node
|
||||
# We start at the buttom of the cidr range + 2 because 0 is not routable and 1 is reserved; hence "i + 2" below
|
||||
node_private_ips = {
|
||||
value = [for i in range(var.instance_count) : "${cidrhost(var.internal_cidr_range, i + 2)}"]
|
||||
}
|
||||
}
|
||||
|
||||
resource "linode_instance" "sfos_nodes" {
|
||||
count = var.instance_count
|
||||
name = "sfos-${count.index}"
|
||||
image = "linode/alpine3.11"
|
||||
label = "sfos"
|
||||
group = "sfos"
|
||||
tags = ["sfos"]
|
||||
region = var.compute_provider_region
|
||||
type = var.compute_provider_node_type
|
||||
authorized_keys = [linode_sshkey.sfos_admin.id]
|
||||
}
|
||||
8
bootstrap/config/add_to_tailnet.tpl
Normal file
8
bootstrap/config/add_to_tailnet.tpl
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#cloud-config
|
||||
users:
|
||||
- name: sfos
|
||||
groups: users, admin
|
||||
sudo: ALL=(ALL) NOPASSWD:ALL
|
||||
shell: /bin/bash
|
||||
ssh_authorized_keys:
|
||||
- ${ admin_ssh_public_key }
|
||||
71
bootstrap/config/nomad-server-blue.config.hcl
Normal file
71
bootstrap/config/nomad-server-blue.config.hcl
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
leave_on_interrupt = true
|
||||
leave_on_terminate = true
|
||||
|
||||
server {
|
||||
enabled = true
|
||||
# Ideally the bootstrap expect value would reflect the number of servers set by `instance_count`, but in the interest
|
||||
# of not chaning each server's "user data" every time the instance_count changes, we hard code the nomad cluster to
|
||||
# bootstrap itself whenever 3 nodes are present
|
||||
bootstrap_expect = 3
|
||||
|
||||
server_join {
|
||||
retry_join = [ "10.0.1.2", "10.0.1.3", "10.0.1.4", "10.0.1.5", "10.0.1.6", "10.0.1.7" ]
|
||||
}
|
||||
}
|
||||
|
||||
acl {
|
||||
enabled = true
|
||||
}
|
||||
|
||||
client {
|
||||
enabled = true
|
||||
|
||||
host_volume "letsencrypt" {
|
||||
path = "/var/www/certbot"
|
||||
read_only = false
|
||||
}
|
||||
|
||||
host_volume "certbot" {
|
||||
path = "/etc/certbot"
|
||||
read_only = false
|
||||
}
|
||||
|
||||
host_network "private" {
|
||||
cidr = "${ private_network_cidr }"
|
||||
}
|
||||
|
||||
host_network "tailnet" {
|
||||
cidr = "100.64.0.0/10"
|
||||
}
|
||||
}
|
||||
|
||||
plugin "docker" {
|
||||
config {
|
||||
gc {
|
||||
image = true
|
||||
image_delay = "3m"
|
||||
container = true
|
||||
|
||||
dangling_containers {
|
||||
enabled = true
|
||||
dry_run = false
|
||||
period = "5m"
|
||||
creation_grace = "5m"
|
||||
}
|
||||
}
|
||||
|
||||
volumes {
|
||||
enabled = true
|
||||
selinuxlabel = "z"
|
||||
}
|
||||
|
||||
allow_caps = ["chown", "net_raw"]
|
||||
allow_privileged = true
|
||||
}
|
||||
}
|
||||
|
||||
plugin "raw_exec" {
|
||||
config {
|
||||
enabled = true
|
||||
}
|
||||
}
|
||||
58
bootstrap/config/nomad-server-cloud-config-blue.tpl
Normal file
58
bootstrap/config/nomad-server-cloud-config-blue.tpl
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
#cloud-config
|
||||
users:
|
||||
- name: sfos
|
||||
groups: users, admin
|
||||
sudo: ALL=(ALL) NOPASSWD:ALL
|
||||
shell: /bin/bash
|
||||
ssh_authorized_keys:
|
||||
- ssh-rsa ${admin_public_key}
|
||||
package_update: true
|
||||
package_upgrade: true
|
||||
packages:
|
||||
- git
|
||||
- bash
|
||||
- apt-transport-https
|
||||
- ca-certificates
|
||||
- software-properties-common
|
||||
|
||||
write_files:
|
||||
- encoding: b64
|
||||
content: ${ install_nomad_script }
|
||||
owner: root:root
|
||||
path: /root/install-nomad.sh
|
||||
permissions: '0755'
|
||||
- encoding: b64
|
||||
content: ${ run_nomad_script }
|
||||
owner: root:root
|
||||
path: /opt/nomad/bin/run-nomad.sh
|
||||
permissions: '0755'
|
||||
- encoding: b64
|
||||
content: ${ nomad_config_file }
|
||||
path: /root/nomad.config.hcl
|
||||
owner: nomad:nomad
|
||||
|
||||
runcmd:
|
||||
- sudo curl -fsSL https://tailscale.com/install.sh | sh
|
||||
- echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf
|
||||
- echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.conf
|
||||
- sudo sysctl -p /etc/sysctl.conf
|
||||
- sudo tailscale up --auth-key ${ tailscale_auth_key } --advertise-routes ${ private_network_cidr }
|
||||
- sleep 2
|
||||
- curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
|
||||
- echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
- sudo echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list
|
||||
- wget -qO- https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo tee /etc/apt/trusted.gpg.d/pgdg.asc &>/dev/null
|
||||
- sudo apt update
|
||||
- apt-cache policy docker-ce
|
||||
- apt install docker-ce restic rclone postgresql-client-15 -y
|
||||
- usermod -G docker -a nomad
|
||||
- /root/install-nomad.sh --version ${ nomad_version } --path /opt/nomad --user root
|
||||
- echo '${ nomad_config_file }' | base64 -d > /opt/nomad/config/custom.hcl
|
||||
- /opt/nomad/bin/run-nomad.sh --server --num-servers 10000 --config-dir /opt/nomad/config --data-dir /opt/nomad/data --bin-dir /opt/nomad/bin
|
||||
- mkdir -p /etc/nginx/conf && mkdir -p /etc/certbot && mkdir -p /var/www/certbot
|
||||
- echo "vm.max_map_count=262144" >> /etc/sysctl.conf
|
||||
- sysctl -p
|
||||
- chmod o+rw /var/run/docker.sock
|
||||
- curl -L -o cni-plugins.tgz https://github.com/containernetworking/plugins/releases/download/v1.1.1/cni-plugins-linux-amd64-v1.1.1.tgz
|
||||
- sudo mkdir -p /opt/cni/bin
|
||||
- sudo tar -C /opt/cni/bin -xzf cni-plugins.tgz
|
||||
26
bootstrap/disko-config.nix
Normal file
26
bootstrap/disko-config.nix
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{lib, ...}: {
|
||||
disko.devices = {
|
||||
disk.disk1 = {
|
||||
device = lib.mkDefault "/dev/sda";
|
||||
content = {
|
||||
type = "table";
|
||||
format = "msdos";
|
||||
partitions = [
|
||||
{
|
||||
part-type = "primary";
|
||||
fs-type = "btrfs";
|
||||
name = "root";
|
||||
bootable = true;
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "btrfs";
|
||||
extraArgs = ["-f" "-O block-group-tree"];
|
||||
mountpoint = "/";
|
||||
mountOptions = ["compress=zstd"];
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
1555
bootstrap/flake.lock
Normal file
1555
bootstrap/flake.lock
Normal file
File diff suppressed because it is too large
Load diff
187
bootstrap/flake.nix
Normal file
187
bootstrap/flake.nix
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
{
|
||||
description = "sfos (self-host os)";
|
||||
nixConfig = {
|
||||
extra-substituters = ["https://microvm.cachix.org"];
|
||||
extra-trusted-public-keys = ["microvm.cachix.org-1:oXnBc6hRE3eX5rSYdRyMYXnfzcCxC7yKPTbZXALsqys="];
|
||||
};
|
||||
|
||||
inputs = {
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
stable.url = "github:NixOS/nixpkgs/nixos-24.05";
|
||||
systems.url = "github:nix-systems/default";
|
||||
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
|
||||
devenv.url = "github:cachix/devenv";
|
||||
disko = {
|
||||
url = "github:nix-community/disko";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
ess = {
|
||||
url = "github:acaloiaro/ess/v2.13.0";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
microvm = {
|
||||
url = "github:astro/microvm.nix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
agenix = {
|
||||
url = "github:ryantm/agenix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
};
|
||||
|
||||
outputs = inputs @ {
|
||||
agenix,
|
||||
devenv,
|
||||
disko,
|
||||
microvm,
|
||||
nixpkgs,
|
||||
self,
|
||||
stable,
|
||||
systems,
|
||||
...
|
||||
}: let
|
||||
inherit (self) outputs;
|
||||
lib = nixpkgs.lib;
|
||||
pkgs = nixpkgs.legacyPackages."x86_64-linux";
|
||||
system = "x86_64-linux";
|
||||
forEachSystem = nixpkgs.lib.genAttrs (import systems);
|
||||
in {
|
||||
inherit lib;
|
||||
packages.${system} = {
|
||||
default = self.packages.${system}.my-microvm;
|
||||
my-microvm = self.nixosConfigurations.my-microvm.config.microvm.declaredRunner;
|
||||
};
|
||||
devShells = forEachSystem (system: let
|
||||
config = self.devShells.${system}.default.config;
|
||||
in {
|
||||
default = devenv.lib.mkShell {
|
||||
inherit inputs pkgs;
|
||||
modules = [
|
||||
{
|
||||
languages = {
|
||||
nix.enable = true;
|
||||
};
|
||||
|
||||
packages = with pkgs; [
|
||||
opentofu
|
||||
pre-commit
|
||||
nixos-anywhere
|
||||
];
|
||||
|
||||
enterShell =
|
||||
#bash
|
||||
''
|
||||
run-show-help
|
||||
'';
|
||||
|
||||
pre-commit.hooks.env-sample-sync = {
|
||||
enable = true;
|
||||
always_run = true;
|
||||
pass_filenames = false;
|
||||
name = "env-sample-sync";
|
||||
description = "Sync secrets to env.sample";
|
||||
entry = "${inputs.ess.packages.${system}.default}/bin/ess";
|
||||
};
|
||||
|
||||
scripts = {
|
||||
run-show-help = {
|
||||
description = "Show this help text";
|
||||
exec = ''
|
||||
echo
|
||||
echo Helper scripts available:
|
||||
echo
|
||||
${pkgs.gnused}/bin/sed -e 's| |XX|g' \
|
||||
-e 's|=| |' <<EOF | \
|
||||
${pkgs.util-linuxMinimal}/bin/column -t | \
|
||||
${pkgs.gnused}/bin/sed -e 's|XX| |g'
|
||||
${pkgs.lib.generators.toKeyValue {} (pkgs.lib.mapAttrs (name: value: value.description) config.scripts)}
|
||||
EOF
|
||||
echo
|
||||
echo To start the web server, the tasks server, create certificates,
|
||||
echo 'add hosts to hostsfiles, dependent services, (redis, et al),'
|
||||
echo just type
|
||||
echo
|
||||
echo " devenv up"
|
||||
echo
|
||||
echo
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
});
|
||||
|
||||
nixosModules = import ./modules/nixos;
|
||||
nixosConfigurations = let
|
||||
nixos-config = {
|
||||
modules,
|
||||
system ? "x86_64-linux",
|
||||
}:
|
||||
nixpkgs.lib.nixosSystem {
|
||||
inherit system;
|
||||
specialArgs = {inherit inputs outputs stable self;};
|
||||
modules =
|
||||
modules
|
||||
++ [
|
||||
disko.nixosModules.disko
|
||||
./disko-config.nix
|
||||
(import ./overlays)
|
||||
agenix.nixosModules.default
|
||||
{environment.systemPackages = [agenix.packages.${system}.default];}
|
||||
./nixos/sfos-host-01/configuration.nix
|
||||
];
|
||||
};
|
||||
microvm-config = {modules}:
|
||||
nixpkgs.lib.nixosSystem {
|
||||
inherit system;
|
||||
specialArgs = {inherit inputs outputs stable self;};
|
||||
modules =
|
||||
modules
|
||||
++ [
|
||||
microvm.nixosModules.microvm
|
||||
{
|
||||
users.users.root.password = "";
|
||||
microvm = {
|
||||
volumes = [
|
||||
{
|
||||
mountPoint = "/var";
|
||||
image = "var.img";
|
||||
size = 1024;
|
||||
}
|
||||
];
|
||||
|
||||
interfaces = [
|
||||
{
|
||||
type = "user";
|
||||
id = "net1";
|
||||
mac = "02:00:00:00:00:01";
|
||||
}
|
||||
];
|
||||
shares = [
|
||||
{
|
||||
# use proto = "virtiofs" for MicroVMs that are started by systemd
|
||||
proto = "9p";
|
||||
tag = "ro-store";
|
||||
# a host's /nix/store will be picked up so that no
|
||||
# squashfs/erofs will be built for it.
|
||||
source = "/nix/store";
|
||||
mountPoint = "/nix/.ro-store";
|
||||
}
|
||||
];
|
||||
|
||||
# "qemu" has 9p built-in!
|
||||
hypervisor = "qemu";
|
||||
socket = "control.socket";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
in {
|
||||
sfos = nixos-config {modules = [./nixos/sfos-host-01/configuration.nix];};
|
||||
my-microvm = microvm-config {modules = [./nixos/sfos-host-01/configuration.nix];};
|
||||
};
|
||||
};
|
||||
}
|
||||
25
bootstrap/hardware-configuration.nix
Normal file
25
bootstrap/hardware-configuration.nix
Normal 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 = [ "ahci" "xhci_pci" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod" ];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ ];
|
||||
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.enp1s0.useDHCP = lib.mkDefault true;
|
||||
# networking.interfaces.enp7s0.useDHCP = lib.mkDefault true;
|
||||
|
||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||
}
|
||||
37
bootstrap/main.tf
Normal file
37
bootstrap/main.tf
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
terraform {
|
||||
backend "s3" {
|
||||
bucket = "mycorp"
|
||||
key = "sfos/sfos-cluster.tfstate"
|
||||
region = "us-east-1"
|
||||
endpoints = {
|
||||
s3 = "https://us-east-1.linodeobjects.com"
|
||||
}
|
||||
skip_credentials_validation = true
|
||||
skip_requesting_account_id = true
|
||||
skip_s3_checksum = true
|
||||
skip_region_validation = true
|
||||
skip_metadata_api_check = true
|
||||
}
|
||||
|
||||
required_providers {
|
||||
tailscale = {
|
||||
source = "tailscale/tailscale"
|
||||
version = "0.17.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "tailscale" {
|
||||
api_key = "my_api_key"
|
||||
tailnet = "example.com"
|
||||
}
|
||||
|
||||
module "compute_provider" {
|
||||
source = "./compute_providers/hetzner"
|
||||
compute_provider_access_token = var.compute_provider_access_token
|
||||
compute_provider_node_type = var.compute_provider_node_type
|
||||
compute_provider_region = var.compute_provider_region
|
||||
admin_ssh_public_key = var.admin_ssh_public_key
|
||||
tailscale_auth_key = var.tailscale_auth_key
|
||||
}
|
||||
|
||||
0
bootstrap/modules/.keep
Normal file
0
bootstrap/modules/.keep
Normal file
0
bootstrap/modules/bootstrap.nix
Normal file
0
bootstrap/modules/bootstrap.nix
Normal file
7
bootstrap/modules/common/qemu.nix
Normal file
7
bootstrap/modules/common/qemu.nix
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{...}: {
|
||||
boot.kernelParams = [
|
||||
"console=tty1"
|
||||
"console=ttyS0,115200"
|
||||
];
|
||||
services.qemuGuest.enable = true;
|
||||
}
|
||||
1
bootstrap/modules/nixos/default.nix
Normal file
1
bootstrap/modules/nixos/default.nix
Normal file
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
78
bootstrap/nixos/common/base-system.nix
Normal file
78
bootstrap/nixos/common/base-system.nix
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
self,
|
||||
...
|
||||
}: {
|
||||
imports = [
|
||||
../../common/nix.nix
|
||||
];
|
||||
|
||||
boot = {
|
||||
initrd.systemd.enable = true;
|
||||
tmp = {
|
||||
cleanOnBoot = true;
|
||||
useTmpfs = true;
|
||||
};
|
||||
|
||||
loader = {
|
||||
efi.canTouchEfiVariables = true;
|
||||
systemd-boot = {
|
||||
enable = true;
|
||||
configurationLimit = 20;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
environment = {
|
||||
systemPackages = with pkgs; [
|
||||
lsof
|
||||
wget
|
||||
];
|
||||
};
|
||||
|
||||
i18n = let
|
||||
locale = "en_US.UTF-8";
|
||||
in {
|
||||
defaultLocale = locale;
|
||||
extraLocaleSettings = {
|
||||
LC_ADDRESS = locale;
|
||||
LC_IDENTIFICATION = locale;
|
||||
LC_MEASUREMENT = locale;
|
||||
LC_MONETARY = locale;
|
||||
LC_NAME = locale;
|
||||
LC_NUMERIC = locale;
|
||||
LC_PAPER = locale;
|
||||
LC_TELEPHONE = locale;
|
||||
LC_TIME = locale;
|
||||
};
|
||||
};
|
||||
|
||||
networking = {
|
||||
enableIPv6 = false;
|
||||
};
|
||||
|
||||
programs = {};
|
||||
|
||||
services = {
|
||||
fstrim.enable = true;
|
||||
locate.enable = true;
|
||||
rsyslogd.enable = true;
|
||||
openssh = {
|
||||
enable = true;
|
||||
settings.PermitRootLogin = "no";
|
||||
};
|
||||
};
|
||||
|
||||
security = {
|
||||
rtkit.enable = true;
|
||||
};
|
||||
|
||||
systemd.services.nix-daemon = {
|
||||
environment.TMPDIR = "/var/tmp";
|
||||
};
|
||||
|
||||
time.timeZone = "America/New_York";
|
||||
users.mutableUsers = false;
|
||||
system.configurationRevision = lib.mkIf (self ? rev) self.rev;
|
||||
}
|
||||
67
bootstrap/nixos/common/incus.nix
Normal file
67
bootstrap/nixos/common/incus.nix
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
with lib; let
|
||||
cfg = config.sfos.incus;
|
||||
in {
|
||||
options.sfos.incus.enable = mkEnableOption "enable incus";
|
||||
options.sfos.incus.admin-users = mkOption {
|
||||
type = with types; listOf str;
|
||||
description = "A list of system users who are incus admins";
|
||||
default = [];
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
virtualisation = {
|
||||
incus = {
|
||||
enable = true;
|
||||
|
||||
# Setup the incus cluster
|
||||
preseed = {
|
||||
networks = [
|
||||
{
|
||||
config = {
|
||||
"ipv4.address" = "10.0.100.1/24";
|
||||
"ipv4.nat" = "true";
|
||||
};
|
||||
name = "incusbr0";
|
||||
type = "bridge";
|
||||
}
|
||||
];
|
||||
profiles = [
|
||||
{
|
||||
devices = {
|
||||
eth0 = {
|
||||
name = "eth0";
|
||||
network = "incusbr0";
|
||||
type = "nic";
|
||||
};
|
||||
root = {
|
||||
path = "/";
|
||||
pool = "default";
|
||||
size = "10GiB";
|
||||
type = "disk";
|
||||
};
|
||||
};
|
||||
name = "default";
|
||||
}
|
||||
];
|
||||
storage_pools = [
|
||||
{
|
||||
config = {
|
||||
source = "/var/lib/incus/storage-pools/default";
|
||||
};
|
||||
driver = "dir";
|
||||
name = "default";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Add users as incus admins
|
||||
users.groups."incus-admin" = mkIf (cfg.admin-users != []) {members = cfg.admin-users;};
|
||||
};
|
||||
}
|
||||
23
bootstrap/nixos/common/podman.nix
Normal file
23
bootstrap/nixos/common/podman.nix
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{pkgs, ...}: {
|
||||
virtualisation = {
|
||||
podman = {
|
||||
enable = true;
|
||||
# Alias all docker commands to podman
|
||||
dockerCompat = true;
|
||||
# Required for containers under podman-compose to be able to talk to each other.
|
||||
defaultNetwork.settings.dns_enabled = true;
|
||||
autoPrune = {
|
||||
enable = true;
|
||||
dates = "weekly";
|
||||
flags = [
|
||||
"--filter=until=24h"
|
||||
# Don't prune containers flagged 'important'
|
||||
"--filter=label!=important"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
environment.systemPackages = with pkgs; [
|
||||
podman-compose
|
||||
];
|
||||
}
|
||||
40
bootstrap/nixos/sfos-host-01/configuration.nix
Normal file
40
bootstrap/nixos/sfos-host-01/configuration.nix
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
{config, ...}: {
|
||||
imports = [
|
||||
../common/base-system.nix
|
||||
../common/podman.nix
|
||||
../common/incus.nix
|
||||
./hardware-configuration.nix
|
||||
../../modules/common/qemu.nix
|
||||
];
|
||||
|
||||
users.users.sfos = {
|
||||
isNormalUser = true;
|
||||
extraGroups = ["wheel"];
|
||||
initialPassword = "Test.123";
|
||||
};
|
||||
|
||||
networking = {
|
||||
hostName = "sfos-host-01";
|
||||
nftables.enable = true;
|
||||
firewall = {
|
||||
allowedTCPPorts = [22];
|
||||
allowedUDPPorts = [config.services.tailscale.port];
|
||||
interfaces.incusbr0.allowedTCPPorts = [
|
||||
22
|
||||
53
|
||||
67
|
||||
];
|
||||
interfaces.incusbr0.allowedUDPPorts = [
|
||||
53
|
||||
67
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
sfos.incus = {
|
||||
enable = true;
|
||||
admin-users = ["sfos"];
|
||||
};
|
||||
services.tailscale.enable = true;
|
||||
system.stateVersion = "24.05";
|
||||
}
|
||||
1
bootstrap/nixos/sfos-host-01/hardware-configuration.nix
Normal file
1
bootstrap/nixos/sfos-host-01/hardware-configuration.nix
Normal file
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
6
bootstrap/overlays/default.nix
Normal file
6
bootstrap/overlays/default.nix
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# This file defines overlays
|
||||
{inputs, ...}: {
|
||||
nixpkgs.overlays = [
|
||||
#(import ./inputs.nix {inherit inputs;})
|
||||
];
|
||||
}
|
||||
3
bootstrap/overlays/inputs.nix
Normal file
3
bootstrap/overlays/inputs.nix
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{inputs, ...}: final: prev: {
|
||||
# exmple = inputs.example.packages.${final.system}.default;
|
||||
}
|
||||
3
bootstrap/todo.md
Normal file
3
bootstrap/todo.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
- Secrets https://github.com/nix-community/nixos-anywhere/blob/main/docs/howtos/secrets.md
|
||||
- Fix partitioning
|
||||
- Get output from tofu to connect and install using nixos-anywhere
|
||||
41
bootstrap/variables.tf
Normal file
41
bootstrap/variables.tf
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
variable "tailscale_auth_key" {
|
||||
type = string
|
||||
description = "Tailscale key for nodes joining the Tailnet"
|
||||
}
|
||||
|
||||
variable "admin_ssh_public_key" {
|
||||
type = string
|
||||
description = "The SSH Public key that can access nodes via SSH after provisioning"
|
||||
}
|
||||
|
||||
variable "node_count" {
|
||||
type = number
|
||||
default = 1
|
||||
description = "the number of nodes to create"
|
||||
}
|
||||
|
||||
variable "internal_cidr_block" {
|
||||
default = "10.0.1.0/24"
|
||||
description = "the cidr block for the cluster's internal subnet"
|
||||
}
|
||||
|
||||
variable "compute_provider_access_token" {
|
||||
type = string
|
||||
description = "Access token for accessing your compute provider's provisioning API"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "compute_provider_node_type" {
|
||||
type = string
|
||||
description = "The name your compute provider uses to refer to the type of compute resource you'll be creating, e.g Hetzner 'cpx21' for CPX21 server"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "compute_provider_region" {
|
||||
description = "Your compute provider's name for the region in which to provision nodes"
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
39
env.sample
39
env.sample
|
|
@ -1,12 +1,37 @@
|
|||
# These credentials are Linode credentials for storing terraform state in a Linode bucket
|
||||
# sfos uses opentofu/terraform to provision infrastrucutre. By default, infrastructure state may be stored in any s3-compatible object store.
|
||||
# Despite the name of this variables, this access key need not be for AWS (Amazon Web Services)
|
||||
#
|
||||
# AWS_ACCESS_KEY_ID is the access key for reading/writing opentofu/terraform state to/from a s3-compatible object store
|
||||
AWS_ACCESS_KEY_ID=<AWS_ACCESS_KEY_ID>
|
||||
|
||||
# sfos uses opentofu/terraform to provision infrastrucutre. By default, infrastructure state may be stored in any s3-compatible object store
|
||||
# Despite the name of this variables, this access key need not be for AWS (Amazon Web Services)
|
||||
#
|
||||
# AWS_SECRET_ACCESS_KEY is the secret access key for reading/writing opentofu/terraform to/from a s3-compatible object store
|
||||
AWS_SECRET_ACCESS_KEY=<AWS_SECRET_ACCESS_KEY>
|
||||
|
||||
# Hetzner DNS API token
|
||||
TF_VAR_hetzner_dns_access_token=<TF_VAR_hetzner_dns_access_token>
|
||||
|
||||
# Hetnzer Compute API token
|
||||
TF_VAR_hetzner_compute_access_token=<TF_VAR_hetzner_compute_access_token>
|
||||
|
||||
# Tailscale key to join the Tailnet
|
||||
TF_VAR_tailscale_auth_key=<TF_VAR_tailscale_auth_key>
|
||||
|
||||
# Access token for accessing your compute provider's provisioning API
|
||||
export TF_VAR_compute_provider_access_token=<TF_VAR_compute_provider_access_token>
|
||||
|
||||
# The SSH public key of the admin user who is able to SSH into created nodes
|
||||
export TF_VAR_admin_ssh_public_key=<TF_VAR_admin_ssh_public_key>
|
||||
|
||||
#######################################################################################################################
|
||||
# Compute provider configuration
|
||||
#######################################################################################################################
|
||||
|
||||
# The name your compute provider uses to refer to the type of compute resource/node you're creating, e.g Hetzner 'cpx21' for CPX21 server
|
||||
export TF_VAR_compute_provider_node_type=<TF_VAR_compute_provider_node_type>
|
||||
|
||||
# The region in which to create compute nodes
|
||||
export TF_VAR_compute_provider_region=<TF_VAR_compute_provider_region>
|
||||
|
||||
# The CIDR block for the cluster's private subnet
|
||||
# export TF_VAR_internal_cidr_block="10.0.1.0/24"
|
||||
|
||||
#######################################################################################################################
|
||||
# Compute provider configuration
|
||||
#######################################################################################################################
|
||||
|
|
|
|||
21
flake.lock
21
flake.lock
|
|
@ -355,6 +355,26 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"disko": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1732742778,
|
||||
"narHash": "sha256-i+Uw8VOHzQe9YdNwKRbzvaPWLE07tYVqUDzSFTXhRgk=",
|
||||
"owner": "nix-community",
|
||||
"repo": "disko",
|
||||
"rev": "341482e2f4d888e3f60cae1c12c3df896e7230d8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "disko",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"ess": {
|
||||
"inputs": {
|
||||
"devenv": "devenv_2",
|
||||
|
|
@ -1382,6 +1402,7 @@
|
|||
"inputs": {
|
||||
"agenix": "agenix",
|
||||
"devenv": "devenv",
|
||||
"disko": "disko",
|
||||
"ess": "ess",
|
||||
"flake-utils": "flake-utils_5",
|
||||
"microvm": "microvm",
|
||||
|
|
|
|||
|
|
@ -12,7 +12,10 @@
|
|||
systems.url = "github:nix-systems/default";
|
||||
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
|
||||
devenv.url = "github:cachix/devenv";
|
||||
|
||||
disko = {
|
||||
url = "github:nix-community/disko";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
ess = {
|
||||
url = "github:acaloiaro/ess/v2.13.0";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
|
|
@ -61,7 +64,9 @@
|
|||
};
|
||||
|
||||
packages = with pkgs; [
|
||||
opentofu
|
||||
pre-commit
|
||||
nixos-anywhere
|
||||
];
|
||||
|
||||
enterShell =
|
||||
|
|
|
|||
Loading…
Reference in a new issue