mirror of
https://github.com/acaloiaro/sfos
synced 2026-07-21 10:12:24 +00:00
WIP
This commit is contained in:
parent
a375a9f940
commit
6a3ee07337
10 changed files with 93 additions and 63 deletions
33
README.md
33
README.md
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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>`
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
7
operate/README.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# Operate
|
||||
|
||||
Add workloads to your cluster.
|
||||
|
||||
## Quick start
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
BIN
secrets/docker_ghcr_auth_config_json.age
Normal file
BIN
secrets/docker_ghcr_auth_config_json.age
Normal file
Binary file not shown.
|
|
@ -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];
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue