1
0
Fork 0

Create files from nixos-wiki-infra

main
Ethan Reece 2025-02-21 05:41:47 -06:00
parent 0c54ab6bef
commit 7e20cace41
Signed by: me
GPG Key ID: 198E9EB433DB1B28
26 changed files with 310 additions and 121 deletions

1
.env.example 100644
View File

@ -0,0 +1 @@
HCLOUD_TOKEN="your_token_here"

2
.gitignore vendored
View File

@ -3,3 +3,5 @@
*.env
*.tfstate
*.tfstate.backup
*.tfstate.*.backup
.terraform.lock.hcl

View File

@ -1,24 +0,0 @@
# This file is maintained automatically by "tofu init".
# Manual edits may be lost in future updates.
provider "registry.opentofu.org/hashicorp/external" {
version = "2.3.4"
hashes = [
"h1:i0CiDzSau8J/NcGlv6A3luRuYkqbnuO2c+XVrJ6YOoA=",
]
}
provider "registry.opentofu.org/hashicorp/null" {
version = "3.2.3"
hashes = [
"h1:tIPswUCP63F9jN+FulrFOJfVriHAMtLUPEkalbwa+Ys=",
]
}
provider "registry.opentofu.org/hetznercloud/hcloud" {
version = "1.49.1"
constraints = "~> 1.45"
hashes = [
"h1:dyK3/rOb8IJOM0trh328NovbYb+Rz33qui2/fg85hU8=",
]
}

View File

@ -4,15 +4,9 @@ This is an experimental configuration for my Hetzner VPS using OpenTofu and Nix.
## How to use
In the `terraform` directory, copy `secret.tfvars.example` to `secret.tfvars` and fill in the values.
Copy `.env.example` to `.env` and fill in the values.
To generate a token with Hetzner, go to the project and click `Security -> API Tokens`.
Run `nix develop` to access a shell where OpenTofu is accessible.
## Aliases
The following aliases in the development shell include the secrets file automatically.
- `tofu-plan` - run in `terraform` directory
- `tofu-apply` - run in `terraform` directory

View File

@ -60,7 +60,28 @@
"inputs": {
"disko": "disko",
"flake-parts": "flake-parts",
"nixpkgs": "nixpkgs"
"nixpkgs": "nixpkgs",
"srvos": "srvos"
}
},
"srvos": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1740012831,
"narHash": "sha256-u6Y5ttXBuQ+tyyCei07QnbNL6Gydv55OpoGh4fXzTqg=",
"owner": "numtide",
"repo": "srvos",
"rev": "f6ddf92bc61e021ea05c971a055624509ffac429",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "srvos",
"type": "github"
}
}
},

View File

@ -7,32 +7,41 @@
disko.url = "github:nix-community/disko";
disko.inputs.nixpkgs.follows = "nixpkgs";
srvos.url = "github:numtide/srvos";
srvos.inputs.nixpkgs.follows = "nixpkgs";
};
outputs = inputs@{ flake-parts, ... }:
outputs = inputs@{ flake-parts, nixpkgs, ... }:
flake-parts.lib.mkFlake { inherit inputs; } {
systems = [
"x86_64-linux"
"aarch64-linux"
];
imports = [
./targets/flake-module.nix
./modules/flake-module.nix
];
perSystem = { system, pkgs, ... }:
let
tofuPkg = pkgs.opentofu.withPlugins (p: [
pkgs.terraform-providers.hcloud
pkgs.terraform-providers.null
pkgs.terraform-providers.external
pkgs.terraform-providers.local
]);
in {
devShells.default = pkgs.mkShell {
buildInputs = [
tofuPkg
pkgs.terraform-ls
pkgs.hcloud
];
shellHook = ''
alias tofu-plan="tofu plan -var-file=secret.tfvars"
alias tofu-apply="tofu apply -var-file=secret.tfvars"
set -a
source ./.env
set +a
'';
};
};

View File

@ -0,0 +1,10 @@
{ inputs, ... }:
{
flake.nixosModules = {
hcloud.imports = [
inputs.srvos.nixosModules.server
inputs.srvos.nixosModules.hardware-hetzner-cloud
./single-disk.nix
];
};
}

View File

@ -0,0 +1,41 @@
{ self, ... }:
let
partitions = {
boot = {
size = "1M";
type = "EF02"; # for grub MBR
};
esp = {
size = "500M";
type = "EF00"; # for grub MBR
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
};
root = {
size = "100%";
content = {
type = "filesystem";
format = "btrfs";
mountpoint = "/";
};
};
};
in
{
imports = [
self.inputs.disko.nixosModules.disko
];
disko.devices = {
disk.sda = {
type = "disk";
device = "/dev/sda";
content = {
type = "gpt";
inherit partitions;
};
};
};
}

View File

@ -0,0 +1,7 @@
#!/usr/bin/env bash
set -euo pipefail
cd "$(dirname "$0")"
rm -f .terraform.lock.hcl
tofu init
tofu apply "$@"

View File

@ -0,0 +1,6 @@
module "vpn" {
source = "../../terraform/admins"
ssh_keys = {
sudoer777 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJWUVBj2uBVfXGjWwXmOTQmqP1oc2ZfDtylhTEox6JBm ssh@sudoer777.dev"
}
}

View File

@ -0,0 +1,26 @@
{ lib, self, ... }:
let
entries = builtins.attrNames (builtins.readDir ./.);
configs = builtins.filter (dir: builtins.pathExists (./. + "/${dir}/configuration.nix")) entries;
in
{
flake.nixosConfigurations = lib.listToAttrs (
builtins.map (
name:
lib.nameValuePair (builtins.replaceStrings [ "." ] [ "-" ] name) (
lib.nixosSystem {
system = "x86_64-linux";
# Make flake available in modules
specialArgs = {
self = {
inputs = self.inputs;
nixosModules = self.nixosModules;
};
};
modules = [ (./. + "/${name}/configuration.nix") ];
}
)
) configs
);
}

View File

@ -0,0 +1,7 @@
#!/usr/bin/env bash
set -euo pipefail
cd "$(dirname "$0")"
rm -f .terraform.lock.hcl
tofu init
tofu apply "$@"

View File

@ -0,0 +1,30 @@
{
self,
lib,
config,
pkgs,
...
}:
let
nixosVars = builtins.fromJSON (builtins.readFile ./nixos-vars.json);
in
{
imports = [
self.nixosModules.hcloud
];
users.users.root.openssh.authorizedKeys.keys = nixosVars.ssh_keys;
system.stateVersion = "23.11";
networking = {
hostName = "vpn";
};
services.openssh = {
enable = true;
settings.PasswordAuthentication = false;
};
boot.supportedFilesystems = ["btrfs"];
environment.systemPackages = [pkgs.btrfs-progs];
}

View File

@ -0,0 +1,15 @@
#!/usr/bin/env bash
set -euxo pipefail
nixBuild() {
if command -v nom -v &>/dev/null; then
nom build "$@"
else
nix build "$@"
fi
}
nixBuild .#nixosConfigurations.vpn.config.system.build.toplevel -L
if ! nixos-rebuild switch --flake .#vpn --target-host root@vpn; then
nixos-rebuild switch --flake .#vpn --target-host root@vpn
fi

View File

@ -0,0 +1 @@
{"ipv6_address":"2a01:4ff:1f0:ce35::1","ssh_keys":["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJWUVBj2uBVfXGjWwXmOTQmqP1oc2ZfDtylhTEox6JBm ssh@sudoer777.dev"]}

View File

@ -0,0 +1,17 @@
module "vpn" {
source = "../../terraform/nixos-vpn"
nixos_flake_attr = "vpn"
nixos_vars_file = "${path.module}/nixos-vars.json"
tags = {
Terraform = "true"
Target = "vpn"
}
}
output "ipv4_address" {
value = module.vpn.ipv4_address
}
output "ipv6_address" {
value = module.vpn.ipv6_address
}

View File

@ -1,24 +0,0 @@
# This file is maintained automatically by "tofu init".
# Manual edits may be lost in future updates.
provider "registry.opentofu.org/hashicorp/external" {
version = "2.3.4"
hashes = [
"h1:i0CiDzSau8J/NcGlv6A3luRuYkqbnuO2c+XVrJ6YOoA=",
]
}
provider "registry.opentofu.org/hashicorp/null" {
version = "3.2.3"
hashes = [
"h1:tIPswUCP63F9jN+FulrFOJfVriHAMtLUPEkalbwa+Ys=",
]
}
provider "registry.opentofu.org/hetznercloud/hcloud" {
version = "1.49.1"
constraints = "~> 1.45"
hashes = [
"h1:dyK3/rOb8IJOM0trh328NovbYb+Rz33qui2/fg85hU8=",
]
}

View File

@ -0,0 +1,8 @@
resource "hcloud_ssh_key" "hcloud" {
for_each = var.ssh_keys
name = each.key
public_key = each.value
labels = {
"wiki" = "true"
}
}

View File

@ -0,0 +1,5 @@
terraform {
required_providers {
hcloud = { source = "hetznercloud/hcloud" }
}
}

View File

@ -0,0 +1,4 @@
variable "ssh_keys" {
type = map(string)
description = "SSH public keys for admin user (name -> key)"
}

View File

@ -1,60 +0,0 @@
terraform {
required_providers {
hcloud = {
source = "hetznercloud/hcloud"
version = "~> 1.45"
}
}
}
variable "hcloud_token" {
sensitive = true
}
provider "hcloud" {
token = var.hcloud_token
}
resource "hcloud_ssh_key" "main" {
name = "my-ssh-key"
public_key = file("~/.ssh/id_ed25519.pub")
}
resource "hcloud_server" "vpn" {
name = "vpn"
image = "debian-12"
server_type = "cpx11"
location = "hil"
ssh_keys = [hcloud_ssh_key.main.id]
//provisioner "local-exec" {
// command = "sleep 120"
//}
//provisioner "remote-exec" {
// connection {
// type = "ssh"
// user = "root"
// host = self.ipv4_address
// // private_key = file("~/.ssh/id_ed25519")
// agent = true
// }
// inline = [
// "curl https://raw.githubusercontent.com/elitak/NixOS-infect/master/NixOS-infect | PROVIDER=hetznercloud Nix_CHANNEL=NixOS-Unstable bash 2>&1 | tee /tmp/infect. log",
// ]
//}
}
module "deploy" {
//depends_on = [local_file.nixos_vars]
source = "github.com/numtide/nixos-anywhere//terraform/all-in-one"
nixos_system_attr = ".#nixosConfigurations.vpn.config.system.build.toplevel"
nixos_partitioner_attr = ".#nixosConfigurations.vpn.config.system.build.diskoScript"
target_host = hcloud_server.vpn.ipv4_address
instance_id = hcloud_server.vpn.id
//extra_files_script = "${path.module}/decrypt-age-keys.sh"
//extra_environment = {
// SOPS_FILE = var.sops_file
//}
debug_logging = true
}

View File

@ -0,0 +1,43 @@
data "hcloud_ssh_keys" "nixos_vpn" {
//with_selector = "vpn=true"
}
resource "hcloud_server" "nixos_vpn" {
name = "nixos-vpn"
image = "debian-12"
keep_disk = true
server_type = var.server_type
location = var.server_location
ssh_keys = data.hcloud_ssh_keys.nixos_vpn.ssh_keys.*.name
backups = false
lifecycle {
ignore_changes = [ssh_keys]
prevent_destroy = true
}
}
module "deploy" {
depends_on = [local_file.nixos_vars]
source = "github.com/numtide/nixos-anywhere//terraform/all-in-one"
nixos_system_attr = ".#nixosConfigurations.vpn.config.system.build.toplevel"
nixos_partitioner_attr = ".#nixosConfigurations.vpn.config.system.build.diskoScriptNoDeps"
target_host = hcloud_server.nixos_vpn.ipv4_address
instance_id = hcloud_server.nixos_vpn.id
debug_logging = true
}
locals {
nixos_vars = {
ipv6_address = hcloud_server.nixos_vpn.ipv6_address
ssh_keys = data.hcloud_ssh_keys.nixos_vpn.ssh_keys.*.public_key
}
}
output "ipv4_address" {
value = hcloud_server.nixos_vpn.ipv4_address
}
output "ipv6_address" {
value = hcloud_server.nixos_vpn.ipv6_address
}

View File

@ -0,0 +1,18 @@
resource "local_file" "nixos_vars" {
content = jsonencode(local.nixos_vars)
filename = var.nixos_vars_file
file_permission = "600"
provisioner "local-exec" {
interpreter = ["bash", "-c"]
command = "git add -f '${var.nixos_vars_file}'"
}
# also pro-actively add hosts and flake-module.nix to git so nix can find it.
provisioner "local-exec" {
interpreter = ["bash", "-c"]
command = <<EOT
git add "$(dirname '${var.nixos_vars_file}')"/{hosts,flake-module.nix}
EOT
on_failure = continue
}
}

View File

@ -0,0 +1,6 @@
terraform {
required_providers {
hcloud = { source = "hetznercloud/hcloud" }
local = { source = "hashicorp/local" }
}
}

View File

@ -0,0 +1,27 @@
variable "server_type" {
type = string
default = "cpx11"
description = "Hetzner cloud server type"
}
variable "server_location" {
type = string
default = "hil"
description = "Hetzner cloud server location"
}
variable "nixos_vars_file" {
type = string
description = "File to write NixOS configuration variables to"
}
variable "nixos_flake_attr" {
type = string
description = "NixOS configuration flake attribute"
}
variable "tags" {
type = map(string)
default = {}
description = "Tags to add to the server"
}

View File

@ -1 +0,0 @@
hcloud_token = "your_token_here"