This commit is contained in:
Adriano Caloiaro 2025-02-10 07:39:49 -07:00
parent a375a9f940
commit 6a3ee07337
No known key found for this signature in database
GPG key ID: C2BC56DE73CE3F75
10 changed files with 93 additions and 63 deletions

View file

@ -5,24 +5,41 @@ Self-host OS.
The goal of this project is a fully-declarative self-hosting platform based on NixOS.
This is not an _actual_ operating system, but a collection of tools and Nix modules, built on top of NixOS, for
bootstrapping and maintaining self-hosted platforms.
bootstrapping and maintaining self-hosted software.
Everything here is currently a work-in-progress.
## Bootstrapping the base system(s)
## Overview
Considering [microvm](https://github.com/astro/microvm.nix/) as the primary bootstrap target for now.
This repository is organized as follows
[TBD](#TBD)
You are here
```
./README.md
```
## Networking
The two most important directories here are
All networking is done with Headscale/tailscale internally, simplifying the interconnection of services.
```
# Bootrap your cluster's resources like compute nodes
./bootstrap
## Virtualization and Containers
# Deploy workloads to your cluster
./operate
```
Each contain README files explaining how to use the modules.
## Quick start
1. `cd ./bootstrap`
2. `cat README.md`
3. Follow the documentation
4. `cd ./operate`
5. `cat README.md`
6. Follow the documentation
[TBD](#TBD)
## Secrets

View file

@ -2,9 +2,22 @@
Stand up a single or multi-machine sfos cluster.
## Get started
## Quick start
1. Edit `main.tf` and point the `compute_provider` module's `source` at the compute provider you want to use, e.g. `source = "./compute_providers/hetzner"`
2. Edit `.env` and plug in values for your compute provider.
3. Run `tofu apply` to create compute resource(s).
4. Run `sfos-init` to initialize the system with your nix configs.
## Configure
### Image registries
#### ghcr.io
1. Create a GitHub classic PAT with permissions (https://github.com/settings/tokens)
[X] repo
[x] write:packages
2. Encode the token in Docker's JSON format: `echo <YOUR PERSONAL ACCESS TOKEN> | docker login ghcr.io -u <GITHUB USERNAME>--password-stdin`
3. `cd ../secrets`
3. Encrypt Docker's JSON file as a secret `cat /var/run/user/$(id -u)/containers/auth.json | EDITOR="cp /dev/stdin" agenix -e docker_ghcr_auth_config_json.age -i <YOUR SSH PRIVATE KEY PATH>`

View file

@ -115,12 +115,12 @@ resource "hcloud_firewall" "allow_ssh" {
#####################################################################################################################
# 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
# }
resource "hcloud_volume" "gp-storage" {
name = "gp-storage"
size = 10
location = var.compute_provider_location
format = "xfs"
delete_protection = true
}

View file

@ -73,6 +73,18 @@ in {
};
};
networking.firewall = {
interfaces.incusbr0.allowedTCPPorts = [
22
53
67
];
interfaces.incusbr0.allowedUDPPorts = [
53
67
];
};
# Add users as incus admins
users.groups."incus-admin" = mkIf (cfg.admin-users != []) {members = cfg.admin-users;};
};

View file

@ -20,7 +20,11 @@
device = "/dev/sda";
};
};
age.secrets.gitea_postgres_password.file = ../../../secrets/gitea_postgres_password.age;
age.secrets.docker_auth_json = {
file = ../../../secrets/docker_ghcr_auth_config_json.age;
path = "/run/containers/0/auth.json";
};
environment.systemPackages = with pkgs; [
umoci
skopeo
@ -51,16 +55,16 @@
};
# Define a systemd service to create files in /var/run/user/0
systemd.services."create-incus-ghcr-auth-file" = {
description = "Create ghcr.io auth file for incus to retrieve private images";
after = ["default.target"];
wantedBy = ["default.target"];
serviceConfig = {
ExecStart = ''${pkgs.bashInteractive}/bin/bash -c 'echo {\\"auths\\":{ \\"ghcr.io\\": {\\"auth\\": \\"YWNhbG9pYXJvOiBnaHBfVnN4dzc4YXZ6N0lBeXQyejVrcGpZQTJXV21XbUZNMzlZdkMxIA==\\"}}} > /var/run/user/0/containers/auth.json' '';
ExecStartPre = "${pkgs.coreutils}/bin/mkdir -p /var/run/user/0/containers";
Restart = "no";
};
};
# systemd.services."create-incus-ghcr-auth-file" = {
# description = "Create ghcr.io auth file for incus to retrieve private images";
# after = ["default.target"];
# wantedBy = ["default.target"];
# serviceConfig = {
# ExecStart = ''${pkgs.bashInteractive}/bin/bash -c 'echo {\\"auths\\":{ \\"ghcr.io\\": {\\"auth\\": \\"YWNhbG9pYXJvOiBnaHBfVnN4dzc4YXZ6N0lBeXQyejVrcGpZQTJXV21XbUZNMzlZdkMxIA==\\"}}} > /var/run/user/0/containers/auth.json' '';
# ExecStartPre = "${pkgs.coreutils}/bin/mkdir -p /var/run/user/0/containers";
# Restart = "no";
# };
# };
#
# /TEST: authentication to private repo
#
@ -73,20 +77,10 @@
};
networking = {
# hostName = "sfos-01";
nftables.enable = true;
firewall = {
allowedTCPPorts = [22 80 443 8443];
allowedUDPPorts = [config.services.tailscale.port];
interfaces.incusbr0.allowedTCPPorts = [
22
53
67
];
interfaces.incusbr0.allowedUDPPorts = [
53
67
];
};
};
services.openssh.enable = true;

View file

@ -49,5 +49,5 @@ export TF_VAR_compute_provider_location=<TF_VAR_compute_provider_location>
#######################################################################################################################
export TF_VAR_ghcr_token=<TF_VAR_ghcr_token>
export TF_VAR_incus_cluster_ip=<TF_VAR_incus_cluster_ip>
export TF_VAR_incus_token=<TF_VAR_incus_token>
export TF_VAR_agenix_public_key=<TF_VAR_agenix_public_key>
export TF_VAR_incus_token=<TF_VAR_incus_token>

7
operate/README.md Normal file
View file

@ -0,0 +1,7 @@
# Operate
Add workloads to your cluster.
## Quick start

View file

@ -25,38 +25,23 @@ provider "incus" {
accept_remote_certificate = true
remote {
name = "sfos-0"
name = var.incus_cluster_ip
scheme = "https"
port = 8443
address = var.incus_cluster_ip
token = var.incus_token
default = true
}
}
resource "incus_network_zone" "default" {
name = "incus.adriano.fyi"
project = "default"
resource "incus_instance" "adriano-fyi" {
name = "adriano-fyi"
image = "ghcr:acaloiaro/adrianofyi"
config = {
"dns.nameservers" = var.incus_cluster_ip
"peers.ns.address" = "127.0.0.1"
}
}
resource "incus_network_zone_record" "default" {
name = "ns"
zone = incus_network_zone.default.name
entry {
type = "CNAME"
value = "incus.adriano.fyi."
ttl = 600
}
entry {
type = "A"
value = var.incus_cluster_ip
ttl = 600
"boot.autostart" = true
"user.caddyserver.http.enable" = true
"user.caddyserver.http.matchers.host" = "adrianofyi.incus.adriano.fyi"
"user.caddyserver.http.upstream.port" = 3000
}
}

Binary file not shown.

View file

@ -1,6 +1,8 @@
# Use ssh-keyscan <SERVER> to fetch the below keys for target systems (SSH server most be running on system)
let
localMachine = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCx/tvR11RUMbYaauuHPxR3j79vm1Hxg+Y3LXR+rLgZ7N/2ulvIzLLZgVuIUbmJHDqkp9Au5zZPMZjsKbaqQ8V75wSEcyaSMbaxC9PaNDCwEHMJWaz8XPQe5IjVRE5O+4sTyh7ZBx+NMQmPcQbrNInoKuy4EjFmwTW/t0xYo/sCrC0NX0cCyeBwii2JdFXytXfxF+RMzGNXw1xfcOFJe6F7JdS/Cpf/0fe+VmNg8d0nic4Obcb/djYsRLAAC6Cvb+4i3EBZWl+9Ih9hId8bFCRKhI6TmGT2z4YUTa+v+3j/JZUh1gD5n4vRGf8QjLj9N6DrBnKcbywwqyqnLhTLgBBN35rcLdU1k3n0NorRRDCU0Lg/ejsFe3oi2FmOwNmmd8zqBNZHjJTi5Wy63EXMFwHltEY2M+hAhgWsQ5U4zuVPgv1HfD6LYPodRwhdZivwTNr2IClAiVVxR//O0WtrRXrrEM5uudj+Y30/ah7bn9Mje86UV0TqfS2tdjtMkySHL+M= adriano@z1";
sfos = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJLQTZC70O2rE4cVDOWlrFLa6mxIJ+B+4gE7eVbmaw2k";
in {
"gitea_postgres_password.age".publicKeys = [localMachine];
"gitea_postgres_password.age".publicKeys = [localMachine sfos];
"docker_ghcr_auth_config_json.age".publicKeys = [localMachine sfos];
}