forked from fediversity/fediversity
Compare commits
39 commits
173518ed90
...
a82bb393a2
| Author | SHA1 | Date | |
|---|---|---|---|
| a82bb393a2 | |||
| 457493c3ee | |||
| 0b11397daa | |||
| 0de70fb9d7 | |||
| f184fd3944 | |||
| 2510b68a68 | |||
| cb69cb41b5 | |||
| da030f8b4f | |||
| 9a9285eaa0 | |||
| 7ab8d3b44e | |||
| d4128d58c7 | |||
| 832fa92fc5 | |||
| c156850fd4 | |||
| 3603b431e0 | |||
| 73bc0fd599 | |||
| 551de1fb51 | |||
| f7000ba9d8 | |||
| 23e9712a06 | |||
| bb94ae3e7d | |||
| 06b7cc5ca2 | |||
| 75addc0c0f | |||
| a9475bb68d | |||
| fad2f46f82 | |||
| 8b85c15df1 | |||
| e4c1a77353 | |||
| 393e92ffe0 | |||
| 585420e589 | |||
| eae3ac83c2 | |||
| 2ab5b12c73 | |||
| a00c83c9a6 | |||
| bb0f3df982 | |||
| 46f00968a3 | |||
| 71bf8c33ec | |||
| b851cad8fd | |||
| 725520ddd4 | |||
| 061314a062 | |||
| 78ecd2db6e | |||
| b645660118 | |||
| 6fcae1c48c |
61 changed files with 1099 additions and 364 deletions
|
|
@ -26,3 +26,9 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: cd panel && nix-build -A tests
|
||||
|
||||
check-launch:
|
||||
runs-on: native
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: cd launch && nix-build -A tests
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
# Deployment
|
||||
|
||||
This repository contains work to generate a full Fediversity deployment from a
|
||||
minimal configuration. This is different from [`../services/`](../services) that
|
||||
focuses on one machine, providing a polished and unified interface to different
|
||||
Fediverse services.
|
||||
|
|
@ -44,138 +44,140 @@ in
|
|||
{ providers, ... }:
|
||||
|
||||
{
|
||||
providers = { inherit (nixops4.modules.nixops4Provider) local; };
|
||||
|
||||
resources =
|
||||
let
|
||||
## NOTE: All of these secrets are publicly available in this source file
|
||||
## and will end up in the Nix store. We don't care as they are only ever
|
||||
## used for testing anyway.
|
||||
##
|
||||
## FIXME: Generate and store in NixOps4's state.
|
||||
mastodonS3KeyConfig =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GK3515373e4c851ebaad366558";
|
||||
s3SecretKeyFile = pkgs.writeText "s3SecretKey" "7d37d093435a41f2aab8f13c19ba067d9776c90215f56614adad6ece597dbb34";
|
||||
};
|
||||
peertubeS3KeyConfig =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GK1f9feea9960f6f95ff404c9b";
|
||||
s3SecretKeyFile = pkgs.writeText "s3SecretKey" "7295c4201966a02c2c3d25b5cea4a5ff782966a2415e3a196f91924631191395";
|
||||
};
|
||||
pixelfedS3KeyConfig =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GKb5615457d44214411e673b7b";
|
||||
s3SecretKeyFile = pkgs.writeText "s3SecretKey" "5be6799a88ca9b9d813d1a806b64f15efa49482dbe15339ddfaf7f19cf434987";
|
||||
};
|
||||
|
||||
makeConfigurationResource = resourceModule: config: {
|
||||
type = providers.local.exec;
|
||||
imports = [
|
||||
nixops4-nixos.modules.nixops4Resource.nixos
|
||||
resourceModule
|
||||
config = {
|
||||
providers = { inherit (nixops4.modules.nixops4Provider) local; };
|
||||
|
||||
resources =
|
||||
let
|
||||
## NOTE: All of these secrets are publicly available in this source file
|
||||
## and will end up in the Nix store. We don't care as they are only ever
|
||||
## used for testing anyway.
|
||||
##
|
||||
## FIXME: Generate and store in NixOps4's state.
|
||||
mastodonS3KeyConfig =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
## NOTE: With NixOps4, there are several levels and all of them live
|
||||
## in the NixOS module system:
|
||||
##
|
||||
## 1. Each NixOps4 deployment is a module.
|
||||
## 2. Each NixOps4 resource is a module. This very comment is
|
||||
## inside an attrset imported as a module in a resource.
|
||||
## 3. Each NixOps4 'configuration' resource contains an attribute
|
||||
## 'nixos.module', itself a NixOS configuration module.
|
||||
nixos.module =
|
||||
{ ... }:
|
||||
{
|
||||
imports = [
|
||||
config
|
||||
fediversity
|
||||
];
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
garage-configuration = makeConfigurationResource garageConfigurationResource (
|
||||
{ pkgs, ... }:
|
||||
mkIf (panelConfig.mastodon.enable || panelConfig.peertube.enable || panelConfig.pixelfed.enable) {
|
||||
fediversity = {
|
||||
inherit (panelConfig) domain;
|
||||
garage.enable = true;
|
||||
pixelfed = pixelfedS3KeyConfig { inherit pkgs; };
|
||||
mastodon = mastodonS3KeyConfig { inherit pkgs; };
|
||||
peertube = peertubeS3KeyConfig { inherit pkgs; };
|
||||
s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GK3515373e4c851ebaad366558";
|
||||
s3SecretKeyFile = pkgs.writeText "s3SecretKey" "7d37d093435a41f2aab8f13c19ba067d9776c90215f56614adad6ece597dbb34";
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
mastodon-configuration = makeConfigurationResource mastodonConfigurationResource (
|
||||
{ pkgs, ... }:
|
||||
mkIf panelConfig.mastodon.enable {
|
||||
fediversity = {
|
||||
inherit (panelConfig) domain;
|
||||
temp.initialUser = {
|
||||
inherit (panelConfig.initialUser) username email displayName;
|
||||
# FIXME: disgusting, but nvm, this is going to be replaced by
|
||||
# proper central authentication at some point
|
||||
passwordFile = pkgs.writeText "password" panelConfig.initialUser.password;
|
||||
};
|
||||
|
||||
mastodon = mastodonS3KeyConfig { inherit pkgs; } // {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
temp.cores = 1; # FIXME: should come from NixOps4 eventually
|
||||
peertubeS3KeyConfig =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GK1f9feea9960f6f95ff404c9b";
|
||||
s3SecretKeyFile = pkgs.writeText "s3SecretKey" "7295c4201966a02c2c3d25b5cea4a5ff782966a2415e3a196f91924631191395";
|
||||
};
|
||||
pixelfedS3KeyConfig =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GKb5615457d44214411e673b7b";
|
||||
s3SecretKeyFile = pkgs.writeText "s3SecretKey" "5be6799a88ca9b9d813d1a806b64f15efa49482dbe15339ddfaf7f19cf434987";
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
peertube-configuration = makeConfigurationResource peertubeConfigurationResource (
|
||||
{ pkgs, ... }:
|
||||
mkIf panelConfig.peertube.enable {
|
||||
fediversity = {
|
||||
inherit (panelConfig) domain;
|
||||
temp.initialUser = {
|
||||
inherit (panelConfig.initialUser) username email displayName;
|
||||
# FIXME: disgusting, but nvm, this is going to be replaced by
|
||||
# proper central authentication at some point
|
||||
passwordFile = pkgs.writeText "password" panelConfig.initialUser.password;
|
||||
};
|
||||
makeConfigurationResource = resourceModule: config: {
|
||||
type = providers.local.exec;
|
||||
imports = [
|
||||
nixops4-nixos.modules.nixops4Resource.nixos
|
||||
resourceModule
|
||||
|
||||
peertube = peertubeS3KeyConfig { inherit pkgs; } // {
|
||||
enable = true;
|
||||
## NOTE: Only ever used for testing anyway.
|
||||
{
|
||||
## NOTE: With NixOps4, there are several levels and all of them live
|
||||
## in the NixOS module system:
|
||||
##
|
||||
## FIXME: Generate and store in NixOps4's state.
|
||||
secretsFile = pkgs.writeText "secret" "574e093907d1157ac0f8e760a6deb1035402003af5763135bae9cbd6abe32b24";
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
## 1. Each NixOps4 deployment is a module.
|
||||
## 2. Each NixOps4 resource is a module. This very comment is
|
||||
## inside an attrset imported as a module in a resource.
|
||||
## 3. Each NixOps4 'configuration' resource contains an attribute
|
||||
## 'nixos.module', itself a NixOS configuration module.
|
||||
nixos.module =
|
||||
{ ... }:
|
||||
{
|
||||
imports = [
|
||||
config
|
||||
fediversity
|
||||
];
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
pixelfed-configuration = makeConfigurationResource pixelfedConfigurationResource (
|
||||
{ pkgs, ... }:
|
||||
mkIf panelConfig.pixelfed.enable {
|
||||
fediversity = {
|
||||
inherit (panelConfig) domain;
|
||||
temp.initialUser = {
|
||||
inherit (panelConfig.initialUser) username email displayName;
|
||||
# FIXME: disgusting, but nvm, this is going to be replaced by
|
||||
# proper central authentication at some point
|
||||
passwordFile = pkgs.writeText "password" panelConfig.initialUser.password;
|
||||
};
|
||||
in
|
||||
|
||||
pixelfed = pixelfedS3KeyConfig { inherit pkgs; } // {
|
||||
enable = true;
|
||||
{
|
||||
garage-configuration = makeConfigurationResource garageConfigurationResource (
|
||||
{ pkgs, ... }:
|
||||
mkIf (panelConfig.mastodon.enable || panelConfig.peertube.enable || panelConfig.pixelfed.enable) {
|
||||
fediversity = {
|
||||
inherit (panelConfig) domain;
|
||||
garage.enable = true;
|
||||
pixelfed = pixelfedS3KeyConfig { inherit pkgs; };
|
||||
mastodon = mastodonS3KeyConfig { inherit pkgs; };
|
||||
peertube = peertubeS3KeyConfig { inherit pkgs; };
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
mastodon-configuration = makeConfigurationResource mastodonConfigurationResource (
|
||||
{ pkgs, ... }:
|
||||
mkIf panelConfig.mastodon.enable {
|
||||
fediversity = {
|
||||
inherit (panelConfig) domain;
|
||||
temp.initialUser = {
|
||||
inherit (panelConfig.initialUser) username email displayName;
|
||||
# FIXME: disgusting, but nvm, this is going to be replaced by
|
||||
# proper central authentication at some point
|
||||
passwordFile = pkgs.writeText "password" panelConfig.initialUser.password;
|
||||
};
|
||||
|
||||
mastodon = mastodonS3KeyConfig { inherit pkgs; } // {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
temp.cores = 1; # FIXME: should come from NixOps4 eventually
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
peertube-configuration = makeConfigurationResource peertubeConfigurationResource (
|
||||
{ pkgs, ... }:
|
||||
mkIf panelConfig.peertube.enable {
|
||||
fediversity = {
|
||||
inherit (panelConfig) domain;
|
||||
temp.initialUser = {
|
||||
inherit (panelConfig.initialUser) username email displayName;
|
||||
# FIXME: disgusting, but nvm, this is going to be replaced by
|
||||
# proper central authentication at some point
|
||||
passwordFile = pkgs.writeText "password" panelConfig.initialUser.password;
|
||||
};
|
||||
|
||||
peertube = peertubeS3KeyConfig { inherit pkgs; } // {
|
||||
enable = true;
|
||||
## NOTE: Only ever used for testing anyway.
|
||||
##
|
||||
## FIXME: Generate and store in NixOps4's state.
|
||||
secretsFile = pkgs.writeText "secret" "574e093907d1157ac0f8e760a6deb1035402003af5763135bae9cbd6abe32b24";
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
pixelfed-configuration = makeConfigurationResource pixelfedConfigurationResource (
|
||||
{ pkgs, ... }:
|
||||
mkIf panelConfig.pixelfed.enable {
|
||||
fediversity = {
|
||||
inherit (panelConfig) domain;
|
||||
temp.initialUser = {
|
||||
inherit (panelConfig.initialUser) username email displayName;
|
||||
# FIXME: disgusting, but nvm, this is going to be replaced by
|
||||
# proper central authentication at some point
|
||||
passwordFile = pkgs.writeText "password" panelConfig.initialUser.password;
|
||||
};
|
||||
|
||||
pixelfed = pixelfedS3KeyConfig { inherit pkgs; } // {
|
||||
enable = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
21
flake.lock
generated
21
flake.lock
generated
|
|
@ -571,6 +571,26 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"home-manager_2": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1743860185,
|
||||
"narHash": "sha256-TkhfJ+vH+iGxLQL6RJLObMmldAQpysVJ+p1WnnKyIeQ=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "b5e29565131802cc8adee7dccede794226da8614",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"mk-naked-shell": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
|
|
@ -1215,6 +1235,7 @@
|
|||
"disko": "disko",
|
||||
"flake-parts": "flake-parts",
|
||||
"git-hooks": "git-hooks",
|
||||
"home-manager": "home-manager_2",
|
||||
"nixops4": "nixops4",
|
||||
"nixops4-nixos": "nixops4-nixos",
|
||||
"nixpkgs": "nixpkgs_7"
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11";
|
||||
flake-parts.url = "github:hercules-ci/flake-parts";
|
||||
git-hooks.url = "github:cachix/git-hooks.nix";
|
||||
home-manager.url = "github:nix-community/home-manager";
|
||||
home-manager.inputs.nixpkgs.follows = "nixpkgs";
|
||||
agenix.url = "github:ryantm/agenix";
|
||||
|
||||
disko.url = "github:nix-community/disko";
|
||||
|
|
@ -43,7 +45,10 @@
|
|||
pre-commit.settings.hooks =
|
||||
let
|
||||
## Add a directory here if pre-commit hooks shouldn't apply to it.
|
||||
optout = [ "npins" ];
|
||||
optout = [
|
||||
"npins"
|
||||
"launch/.terraform"
|
||||
];
|
||||
excludes = map (dir: "^${dir}/") optout;
|
||||
addExcludes = lib.mapAttrs (_: c: c // { inherit excludes; });
|
||||
in
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
let
|
||||
inherit (lib) mkDefault;
|
||||
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ in
|
|||
imports = [
|
||||
inputs.agenix.nixosModules.default
|
||||
inputs.disko.nixosModules.default
|
||||
inputs.home-manager.nixosModules.home-manager
|
||||
./options.nix
|
||||
./nixos
|
||||
];
|
||||
|
|
|
|||
9
infra/dev/.terraform.lock.hcl
generated
Normal file
9
infra/dev/.terraform.lock.hcl
generated
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# 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:hBFp4dEKKevoZEsMW32ralBqrO7cTxTPYdWPqc4Ff+s=",
|
||||
]
|
||||
}
|
||||
1
infra/dev/.terraform/modules/modules.json
Normal file
1
infra/dev/.terraform/modules/modules.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"Modules":[{"Key":"","Source":"","Dir":"."},{"Key":"nixos","Source":"../sync-nix","Dir":"../sync-nix"}]}
|
||||
3
infra/dev/.terraform/plugin_path
Normal file
3
infra/dev/.terraform/plugin_path
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
[
|
||||
"/nix/store/zbjjm6vgdj1p2v21qshd9np3ajdnhniy-opentofu-1.9.0/libexec/terraform-providers"
|
||||
]
|
||||
1
infra/dev/.terraform/providers/registry.opentofu.org/hashicorp/external/2.3.4/linux_amd64
vendored
Symbolic link
1
infra/dev/.terraform/providers/registry.opentofu.org/hashicorp/external/2.3.4/linux_amd64
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
/nix/store/zbjjm6vgdj1p2v21qshd9np3ajdnhniy-opentofu-1.9.0/libexec/terraform-providers/registry.opentofu.org/hashicorp/external/2.3.4/linux_amd64
|
||||
1
infra/dev/terraform.tfstate
Normal file
1
infra/dev/terraform.tfstate
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":4,"terraform_version":"1.9.0","serial":7,"lineage":"c441e8b7-409b-c7ad-85b9-27549f9ee16d","outputs":{},"resources":[{"module":"module.nixos[\"fedipanel\"]","mode":"data","type":"external","name":"hash","provider":"provider[\"registry.opentofu.org/hashicorp/external\"]","instances":[{"schema_version":0,"attributes":{"id":"-","program":["sh","-c","echo \"{\\\"hash\\\":\\\"$(nix-hash ..)\\\"}\""],"query":null,"result":{"hash":"104476c354d745011877f63e653ae58b"},"working_dir":null},"sensitive_attributes":[]}]},{"module":"module.nixos[\"fedipanel\"]","mode":"managed","type":"terraform_data","name":"nixos","provider":"provider[\"terraform.io/builtin/terraform\"]","instances":[{"schema_version":0,"attributes":{"id":"909398aa-e751-1dc8-a61a-7eb33df17006","input":null,"output":null,"triggers_replace":{"value":[{"hash":"104476c354d745011877f63e653ae58b"},"fedi201","{\n # note interpolations here TF ones\n imports = [\n # shared NixOS config\n ./../common/shared.nix\n # FIXME: separate template options by service\n ./options.nix\n # for service `forgejo` import `forgejo.nix`\n ./../../machines/dev/fedi201/fedipanel.nix\n # FIXME: get VM details from TF\n ./../../machines/dev/fedi201\n ];\n}\n",{"terraform":{"domain":"abundos.eu","hostname":"fedi201"}}],"type":["tuple",[["map","string"],"string","string",["map",["object",{"domain":"string","hostname":"string"}]]]]}},"sensitive_attributes":[],"dependencies":["module.nixos.data.external.hash"]}]}],"check_results":null}
|
||||
1
infra/dev/terraform.tfstate.backup
Normal file
1
infra/dev/terraform.tfstate.backup
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":4,"terraform_version":"1.9.0","serial":5,"lineage":"c441e8b7-409b-c7ad-85b9-27549f9ee16d","outputs":{},"resources":[{"module":"module.nixos[\"fedipanel\"]","mode":"data","type":"external","name":"hash","provider":"provider[\"registry.opentofu.org/hashicorp/external\"]","instances":[{"schema_version":0,"attributes":{"id":"-","program":["sh","-c","echo \"{\\\"hash\\\":\\\"$(nix-hash ..)\\\"}\""],"query":null,"result":{"hash":"c9bc7d95c831fa099e803674e850b509"},"working_dir":null},"sensitive_attributes":[]}]},{"module":"module.nixos[\"fedipanel\"]","mode":"managed","type":"terraform_data","name":"nixos","provider":"provider[\"terraform.io/builtin/terraform\"]","instances":[{"status":"tainted","schema_version":0,"attributes":{"id":"16edc410-f42a-0489-5326-65fa4b53cf31","input":null,"output":null,"triggers_replace":{"value":[{"hash":"c9bc7d95c831fa099e803674e850b509"},"fedi201","{\n # note interpolations here TF ones\n imports = [\n # shared NixOS config\n ./../common/shared.nix\n # FIXME: separate template options by service\n ./options.nix\n # for service `forgejo` import `forgejo.nix`\n ./../../machines/dev/fedi201/fedipanel.nix\n # FIXME: get VM details from TF\n ./../../machines/dev/fedi201\n ];\n}\n",{"terraform":{"domain":"abundos.eu","hostname":"fedi201"}}],"type":["tuple",[["map","string"],"string","string",["map",["object",{"domain":"string","hostname":"string"}]]]]}},"sensitive_attributes":[],"dependencies":["module.nixos.data.external.hash"]}]}],"check_results":null}
|
||||
|
|
@ -1,12 +1,11 @@
|
|||
{
|
||||
self,
|
||||
inputs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (builtins) readDir readFile fromJSON;
|
||||
inherit (builtins) readDir;
|
||||
inherit (lib)
|
||||
attrNames
|
||||
mkOption
|
||||
|
|
@ -15,33 +14,17 @@ let
|
|||
;
|
||||
inherit (lib.attrsets) genAttrs;
|
||||
|
||||
## Given a machine's name and whether it is a test VM, make a resource module,
|
||||
## Given a machine's name, make a resource module,
|
||||
## except for its missing provider. (Depending on the use of that resource, we
|
||||
## will provide a different one.)
|
||||
makeResourceModule =
|
||||
{ vmName, isTestVm }:
|
||||
{ vmName }:
|
||||
{
|
||||
_module.args = { inherit inputs; };
|
||||
imports =
|
||||
[
|
||||
./common/resource.nix
|
||||
]
|
||||
++ (
|
||||
if isTestVm then
|
||||
[
|
||||
./test-machines/${vmName}
|
||||
{
|
||||
nixos.module.users.users.root.openssh.authorizedKeys.keys = [
|
||||
# allow our panel vm access to the test machines
|
||||
(import ../keys).panel
|
||||
];
|
||||
}
|
||||
]
|
||||
else
|
||||
[
|
||||
./machines/${vmName}
|
||||
]
|
||||
);
|
||||
imports = [
|
||||
./common/resource.nix
|
||||
./machines/${vmName}
|
||||
];
|
||||
fediversityVm.name = vmName;
|
||||
};
|
||||
|
||||
|
|
@ -58,42 +41,12 @@ let
|
|||
inputs.nixops4-nixos.modules.nixops4Resource.nixos
|
||||
(makeResourceModule {
|
||||
inherit vmName;
|
||||
isTestVm = false;
|
||||
})
|
||||
];
|
||||
});
|
||||
};
|
||||
makeDeployment' = vmName: makeDeployment [ vmName ];
|
||||
|
||||
## Given an attrset of test configurations (key = test machine name, value =
|
||||
## NixOS configuration module), make a deployment with those machines'
|
||||
## configurations as resources.
|
||||
makeTestDeployment =
|
||||
(import ../deployment)
|
||||
{
|
||||
inherit lib;
|
||||
inherit (inputs) nixops4 nixops4-nixos;
|
||||
inherit (self.nixosModules) fediversity;
|
||||
}
|
||||
{
|
||||
garageConfigurationResource = makeResourceModule {
|
||||
vmName = "test01";
|
||||
isTestVm = true;
|
||||
};
|
||||
mastodonConfigurationResource = makeResourceModule {
|
||||
vmName = "test06"; # somehow `test02` has a problem - use test06 instead
|
||||
isTestVm = true;
|
||||
};
|
||||
peertubeConfigurationResource = makeResourceModule {
|
||||
vmName = "test05";
|
||||
isTestVm = true;
|
||||
};
|
||||
pixelfedConfigurationResource = makeResourceModule {
|
||||
vmName = "test04";
|
||||
isTestVm = true;
|
||||
};
|
||||
};
|
||||
|
||||
nixops4ResourceNixosMockOptions = {
|
||||
## NOTE: We allow the use of a few options from
|
||||
## `inputs.nixops4-nixos.modules.nixops4Resource.nixos` such that we can
|
||||
|
|
@ -120,15 +73,15 @@ let
|
|||
|
||||
## Given a VM name, make a NixOS configuration for this machine.
|
||||
makeConfiguration =
|
||||
isTestVm: vmName:
|
||||
vmName:
|
||||
inputs.nixpkgs.lib.nixosSystem {
|
||||
modules = [
|
||||
(makeResourceConfig { inherit vmName isTestVm; }).nixos.module
|
||||
(makeResourceConfig { inherit vmName; }).nixos.module
|
||||
];
|
||||
};
|
||||
|
||||
makeVmOptions = isTestVm: vmName: {
|
||||
inherit ((makeResourceConfig { inherit vmName isTestVm; }).fediversityVm)
|
||||
makeVmOptions = vmName: {
|
||||
inherit ((makeResourceConfig { inherit vmName; }).fediversityVm)
|
||||
proxmox
|
||||
vmId
|
||||
description
|
||||
|
|
@ -146,35 +99,18 @@ let
|
|||
listSubdirectories = path: attrNames (filterAttrs (_: type: type == "directory") (readDir path));
|
||||
|
||||
machines = listSubdirectories ./machines;
|
||||
testMachines = listSubdirectories ./test-machines;
|
||||
|
||||
in
|
||||
{
|
||||
flake.lib.makeInstallerIso = import ./makeInstallerIso.nix;
|
||||
|
||||
## - Each normal or test machine gets a NixOS configuration.
|
||||
## - Each normal or test machine gets a VM options entry.
|
||||
## - Each normal machine gets a deployment.
|
||||
## - We add a “default” deployment with all normal machines.
|
||||
## - We add a “test” deployment with all test machines.
|
||||
## - Each machine gets a NixOS configuration.
|
||||
## - Each machine gets a VM options entry.
|
||||
## - Each machine gets a deployment.
|
||||
## - We add a “default” deployment with all infra machines.
|
||||
nixops4Deployments = genAttrs machines makeDeployment' // {
|
||||
default = makeDeployment machines;
|
||||
test = makeTestDeployment (
|
||||
fromJSON (
|
||||
let
|
||||
env = builtins.getEnv "DEPLOYMENT";
|
||||
in
|
||||
if env != "" then
|
||||
env
|
||||
else
|
||||
builtins.trace "env var DEPLOYMENT not set, falling back to ./test-machines/configuration.json!" (readFile ./test-machines/configuration.json)
|
||||
)
|
||||
);
|
||||
};
|
||||
flake.nixosConfigurations =
|
||||
genAttrs machines (makeConfiguration false)
|
||||
// genAttrs testMachines (makeConfiguration true);
|
||||
flake.vmOptions =
|
||||
genAttrs machines (makeVmOptions false)
|
||||
// genAttrs testMachines (makeVmOptions true);
|
||||
flake.nixosConfigurations = genAttrs machines makeConfiguration;
|
||||
flake.vmOptions = genAttrs machines makeVmOptions;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,24 @@ in
|
|||
enable = true;
|
||||
production = true;
|
||||
domain = "demo.fediversity.eu";
|
||||
# FIXME: make it work without this duplication
|
||||
settings =
|
||||
let
|
||||
cfg = config.services.${name};
|
||||
in
|
||||
{
|
||||
STATIC_ROOT = "/var/lib/${name}/static";
|
||||
DEBUG = false;
|
||||
ALLOWED_HOSTS = [
|
||||
cfg.domain
|
||||
cfg.host
|
||||
"localhost"
|
||||
"[::1]"
|
||||
];
|
||||
CSRF_TRUSTED_ORIGINS = [ "https://${cfg.domain}" ];
|
||||
COMPRESS_OFFLINE = true;
|
||||
LIBSASS_OUTPUT_STYLE = "compressed";
|
||||
};
|
||||
secrets = {
|
||||
SECRET_KEY = config.age.secrets.panel-secret-key.path;
|
||||
};
|
||||
|
|
|
|||
9
infra/operator/.terraform.lock.hcl
generated
Normal file
9
infra/operator/.terraform.lock.hcl
generated
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# 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:hBFp4dEKKevoZEsMW32ralBqrO7cTxTPYdWPqc4Ff+s=",
|
||||
]
|
||||
}
|
||||
1
infra/operator/.terraform/modules/modules.json
Normal file
1
infra/operator/.terraform/modules/modules.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"Modules":[{"Key":"","Source":"","Dir":"."},{"Key":"nixos","Source":"../sync-nix","Dir":"../sync-nix"}]}
|
||||
3
infra/operator/.terraform/plugin_path
Normal file
3
infra/operator/.terraform/plugin_path
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
[
|
||||
"/nix/store/zbjjm6vgdj1p2v21qshd9np3ajdnhniy-opentofu-1.9.0/libexec/terraform-providers"
|
||||
]
|
||||
1
infra/operator/.terraform/providers/registry.opentofu.org/hashicorp/external/2.3.4/linux_amd64
vendored
Symbolic link
1
infra/operator/.terraform/providers/registry.opentofu.org/hashicorp/external/2.3.4/linux_amd64
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
/nix/store/zbjjm6vgdj1p2v21qshd9np3ajdnhniy-opentofu-1.9.0/libexec/terraform-providers/registry.opentofu.org/hashicorp/external/2.3.4/linux_amd64
|
||||
1
infra/operator/terraform.tfstate
Normal file
1
infra/operator/terraform.tfstate
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":4,"terraform_version":"1.9.0","serial":7,"lineage":"b39bdfbe-91a7-d39b-96f5-71d9e0c9d47f","outputs":{},"resources":[{"module":"module.nixos[\"garage\"]","mode":"data","type":"external","name":"hash","provider":"provider[\"registry.opentofu.org/hashicorp/external\"]","instances":[{"schema_version":0,"attributes":{"id":"-","program":["sh","-c","echo \"{\\\"hash\\\":\\\"$(nix-hash ..)\\\"}\""],"query":null,"result":{"hash":"a871537a6a7f4dbf5614ebaff5005606"},"working_dir":null},"sensitive_attributes":[]}]},{"module":"module.nixos[\"garage\"]","mode":"managed","type":"terraform_data","name":"nixos","provider":"provider[\"terraform.io/builtin/terraform\"]","instances":[{"schema_version":0,"attributes":{"id":"79db5288-d7d6-24e4-4f23-5bfc353c97b9","input":null,"output":null,"triggers_replace":{"value":[{"hash":"a871537a6a7f4dbf5614ebaff5005606"},"test01","{\n # note interpolations here TF ones\n imports = [\n # shared NixOS config\n ./../common/shared.nix\n # FIXME: separate template options by service\n ./options.nix\n # for service `mastodon` import `mastodon.nix`\n ./../../machines/operator/test01/garage.nix\n # FIXME: get VM details from TF\n ./../../machines/operator/test01\n ];\n ## FIXME: switch root authentication to users with password-less sudo, see #24\n users.users.root.openssh.authorizedKeys.keys = let\n keys = import ../../keys;\n in builtins.attrValues keys.contributors ++ [\n # allow our panel vm access to the test machines\n keys.panel\n ];\n}\n",{"terraform":{"domain":"fediversity.net","hostname":"test01","initialUser":{"displayName":"Testy McTestface","email":"test@test.com","password":"testtest","username":"test"}}}],"type":["tuple",[["map","string"],"string","string",["map",["object",{"domain":"string","hostname":"string","initialUser":["object",{"displayName":"string","email":"string","password":"string","username":"string"}]}]]]]}},"sensitive_attributes":[],"dependencies":["module.nixos.data.external.hash"]}]},{"module":"module.nixos[\"mastodon\"]","mode":"data","type":"external","name":"hash","provider":"provider[\"registry.opentofu.org/hashicorp/external\"]","instances":[{"schema_version":0,"attributes":{"id":"-","program":["sh","-c","echo \"{\\\"hash\\\":\\\"$(nix-hash ..)\\\"}\""],"query":null,"result":{"hash":"a871537a6a7f4dbf5614ebaff5005606"},"working_dir":null},"sensitive_attributes":[]}]},{"module":"module.nixos[\"mastodon\"]","mode":"managed","type":"terraform_data","name":"nixos","provider":"provider[\"terraform.io/builtin/terraform\"]","instances":[{"schema_version":0,"attributes":{"id":"fde5cd73-a82c-c8ee-becd-51e2822652c4","input":null,"output":null,"triggers_replace":{"value":[{"hash":"a871537a6a7f4dbf5614ebaff5005606"},"test06","{\n # note interpolations here TF ones\n imports = [\n # shared NixOS config\n ./../common/shared.nix\n # FIXME: separate template options by service\n ./options.nix\n # for service `mastodon` import `mastodon.nix`\n ./../../machines/operator/test06/mastodon.nix\n # FIXME: get VM details from TF\n ./../../machines/operator/test06\n ];\n ## FIXME: switch root authentication to users with password-less sudo, see #24\n users.users.root.openssh.authorizedKeys.keys = let\n keys = import ../../keys;\n in builtins.attrValues keys.contributors ++ [\n # allow our panel vm access to the test machines\n keys.panel\n ];\n}\n",{"terraform":{"domain":"fediversity.net","hostname":"test06","initialUser":{"displayName":"Testy McTestface","email":"test@test.com","password":"testtest","username":"test"}}}],"type":["tuple",[["map","string"],"string","string",["map",["object",{"domain":"string","hostname":"string","initialUser":["object",{"displayName":"string","email":"string","password":"string","username":"string"}]}]]]]}},"sensitive_attributes":[],"dependencies":["module.nixos.data.external.hash"]}]}],"check_results":null}
|
||||
1
infra/operator/terraform.tfstate.backup
Normal file
1
infra/operator/terraform.tfstate.backup
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":4,"terraform_version":"1.9.0","serial":4,"lineage":"b39bdfbe-91a7-d39b-96f5-71d9e0c9d47f","outputs":{},"resources":[{"module":"module.nixos[\"garage\"]","mode":"data","type":"external","name":"hash","provider":"provider[\"registry.opentofu.org/hashicorp/external\"]","instances":[{"schema_version":0,"attributes":{"id":"-","program":["sh","-c","echo \"{\\\"hash\\\":\\\"$(nix-hash ..)\\\"}\""],"query":null,"result":{"hash":"02bdde9db2e3d40aaabcb0fd5bf5939b"},"working_dir":null},"sensitive_attributes":[]}]},{"module":"module.nixos[\"garage\"]","mode":"managed","type":"terraform_data","name":"nixos","provider":"provider[\"terraform.io/builtin/terraform\"]","instances":[{"status":"tainted","schema_version":0,"attributes":{"id":"618c1781-9035-8b5a-573a-53ff5407256b","input":null,"output":null,"triggers_replace":{"value":[{"hash":"02bdde9db2e3d40aaabcb0fd5bf5939b"},"test01","{\n # note interpolations here TF ones\n imports = [\n # shared NixOS config\n ./../common/shared.nix\n # FIXME: separate template options by service\n ./options.nix\n # for service `mastodon` import `mastodon.nix`\n ./../../machines/operator/test01/garage.nix\n # FIXME: get VM details from TF\n ./../../machines/operator/test01\n ];\n ## FIXME: switch root authentication to users with password-less sudo, see #24\n users.users.root.openssh.authorizedKeys.keys = let\n keys = import ../keys;\n in builtins.attrValues keys.contributors ++ [\n # allow our panel vm access to the test machines\n keys.panel\n ];\n}\n",{"terraform":{"domain":"fediversity.net","hostname":"test01","initialUser":{"displayName":"Testy McTestface","email":"test@test.com","password":"testtest","username":"test"}}}],"type":["tuple",[["map","string"],"string","string",["map",["object",{"domain":"string","hostname":"string","initialUser":["object",{"displayName":"string","email":"string","password":"string","username":"string"}]}]]]]}},"sensitive_attributes":[],"dependencies":["module.nixos.data.external.hash"]}]},{"module":"module.nixos[\"mastodon\"]","mode":"data","type":"external","name":"hash","provider":"provider[\"registry.opentofu.org/hashicorp/external\"]","instances":[{"schema_version":0,"attributes":{"id":"-","program":["sh","-c","echo \"{\\\"hash\\\":\\\"$(nix-hash ..)\\\"}\""],"query":null,"result":{"hash":"02bdde9db2e3d40aaabcb0fd5bf5939b"},"working_dir":null},"sensitive_attributes":[]}]},{"module":"module.nixos[\"mastodon\"]","mode":"managed","type":"terraform_data","name":"nixos","provider":"provider[\"terraform.io/builtin/terraform\"]","instances":[{"status":"tainted","schema_version":0,"attributes":{"id":"00be3f3d-b7c2-1356-a62c-8eb3106fc7d5","input":null,"output":null,"triggers_replace":{"value":[{"hash":"02bdde9db2e3d40aaabcb0fd5bf5939b"},"test06","{\n # note interpolations here TF ones\n imports = [\n # shared NixOS config\n ./../common/shared.nix\n # FIXME: separate template options by service\n ./options.nix\n # for service `mastodon` import `mastodon.nix`\n ./../../machines/operator/test06/mastodon.nix\n # FIXME: get VM details from TF\n ./../../machines/operator/test06\n ];\n ## FIXME: switch root authentication to users with password-less sudo, see #24\n users.users.root.openssh.authorizedKeys.keys = let\n keys = import ../keys;\n in builtins.attrValues keys.contributors ++ [\n # allow our panel vm access to the test machines\n keys.panel\n ];\n}\n",{"terraform":{"domain":"fediversity.net","hostname":"test06","initialUser":{"displayName":"Testy McTestface","email":"test@test.com","password":"testtest","username":"test"}}}],"type":["tuple",[["map","string"],"string","string",["map",["object",{"domain":"string","hostname":"string","initialUser":["object",{"displayName":"string","email":"string","password":"string","username":"string"}]}]]]]}},"sensitive_attributes":[],"dependencies":["module.nixos.data.external.hash"]}]}],"check_results":null}
|
||||
1
infra/sync-nix/.npins.json
Normal file
1
infra/sync-nix/.npins.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"agenix":"/nix/store/glsqq1xn5al7d528hvlbm4hl3ladxmka-source","disko":"/nix/store/7wf9q0mb1i43x9dr1qlyfaraq15n6sii-source","flake-inputs":"/nix/store/fqln0bcp6mp75k4sl0cav2f0np60lwhj-source","git-hooks":"/nix/store/8bh3jgq1riy3jxm07vy4xxzvk9xd74pc-source","gitignore":"/nix/store/g5v3sgqy6a0fsmas7mnapc196flrplix-source","home-manager":"/nix/store/cq3b3cx5rv9d0zj57kch9wmxzc2rm8dc-source","htmx":"/nix/store/mwqqk0qmldzvv4xj9kq2lbah2flhc44z-source","nix-unit":"/nix/store/4g1vvy7bhwh16cyd2r8ibq7n6ygk1wvk-source","nixpkgs":"/nix/store/g1bajdwbkcmms8cqd9s8zbq8zxhkyx91-source"}
|
||||
9
infra/sync-nix/.terraform.lock.hcl
generated
Normal file
9
infra/sync-nix/.terraform.lock.hcl
generated
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# 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:hBFp4dEKKevoZEsMW32ralBqrO7cTxTPYdWPqc4Ff+s=",
|
||||
]
|
||||
}
|
||||
3
infra/sync-nix/.terraform/plugin_path
Normal file
3
infra/sync-nix/.terraform/plugin_path
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
[
|
||||
"/nix/store/zbjjm6vgdj1p2v21qshd9np3ajdnhniy-opentofu-1.9.0/libexec/terraform-providers"
|
||||
]
|
||||
1
infra/sync-nix/.terraform/providers/registry.opentofu.org/hashicorp/external/2.3.4/linux_amd64
vendored
Symbolic link
1
infra/sync-nix/.terraform/providers/registry.opentofu.org/hashicorp/external/2.3.4/linux_amd64
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
/nix/store/zbjjm6vgdj1p2v21qshd9np3ajdnhniy-opentofu-1.9.0/libexec/terraform-providers/registry.opentofu.org/hashicorp/external/2.3.4/linux_amd64
|
||||
|
|
@ -1 +1 @@
|
|||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEElREJN0AC7lbp+5X204pQ5r030IbgCllsIxyU3iiKY niols@wallace
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICJj4L5Yt9ABdQeEkJI6VuJEyUSVbCHMxYLdvVcB/pXh niols@wallace/fediversity
|
||||
|
|
|
|||
10
launch/.envrc
Normal file
10
launch/.envrc
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#!/usr/bin/env bash
|
||||
# the shebang is ignored, but nice for editors
|
||||
|
||||
# shellcheck shell=bash
|
||||
if type -P lorri &>/dev/null; then
|
||||
eval "$(lorri direnv --flake .)"
|
||||
else
|
||||
echo 'while direnv evaluated .envrc, could not find the command "lorri" [https://github.com/nix-community/lorri]'
|
||||
use flake
|
||||
fi
|
||||
7
launch/.gitignore
vendored
Normal file
7
launch/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# generated
|
||||
.auto.tfvars.json
|
||||
.npins.json
|
||||
.terraform/
|
||||
.terraform.lock.hcl
|
||||
.terraform.tfstate.lock.info
|
||||
terraform.tfstate*
|
||||
28
launch/README.md
Normal file
28
launch/README.md
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# service deployment
|
||||
|
||||
deploys [NixOS](https://nixos.org/) templates using [OpenTofu](https://opentofu.org/).
|
||||
|
||||
## requirements
|
||||
|
||||
- [nix](https://nix.dev/)
|
||||
|
||||
## usage
|
||||
|
||||
### development
|
||||
|
||||
before using other commands, if not using direnv:
|
||||
|
||||
```sh
|
||||
nix-shell
|
||||
```
|
||||
|
||||
then to initialize, or after updating pins or TF providers:
|
||||
|
||||
```sh
|
||||
setup
|
||||
```
|
||||
|
||||
## implementing
|
||||
|
||||
proper documentation TODO.
|
||||
until then, a reference implementation may be found in [`panel/`](https://git.fediversity.eu/Fediversity/Fediversity/src/branch/main/panel).
|
||||
41
launch/default.nix
Normal file
41
launch/default.nix
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
system ? builtins.currentSystem,
|
||||
sources ? import ../npins,
|
||||
# match the same versions we deploy locally
|
||||
inputs ? import sources.flake-inputs {
|
||||
root = ../.;
|
||||
},
|
||||
# match the same version of opentofu that is deployed by the root flake
|
||||
pkgs ? import inputs.nixpkgs {
|
||||
inherit system;
|
||||
},
|
||||
}:
|
||||
let
|
||||
inherit (pkgs) lib;
|
||||
setup = pkgs.writeScriptBin "setup" ''
|
||||
echo '${lib.strings.toJSON sources}' > .npins.json
|
||||
rm -f .terraform.lock.hcl
|
||||
rm -rf .terraform/
|
||||
tofu init
|
||||
'';
|
||||
in
|
||||
{
|
||||
# shell for testing TF directly
|
||||
shell = pkgs.mkShellNoCC {
|
||||
packages = [
|
||||
(import ./tf.nix { inherit lib pkgs; })
|
||||
pkgs.jaq
|
||||
setup
|
||||
];
|
||||
};
|
||||
|
||||
tests = pkgs.callPackage ./tests.nix { };
|
||||
|
||||
# re-export inputs so they can be overridden granularly
|
||||
# (they can't be accessed from the outside any other way)
|
||||
inherit
|
||||
sources
|
||||
system
|
||||
pkgs
|
||||
;
|
||||
}
|
||||
34
launch/garage.nix
Normal file
34
launch/garage.nix
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
{ pkgs, ... }:
|
||||
let
|
||||
## NOTE: All of these secrets are publicly available in this source file
|
||||
## and will end up in the Nix store. We don't care as they are only ever
|
||||
## used for testing anyway.
|
||||
##
|
||||
## FIXME: Generate and store in NixOps4's state.
|
||||
mastodonS3KeyConfig =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GK3515373e4c851ebaad366558";
|
||||
s3SecretKeyFile = pkgs.writeText "s3SecretKey" "7d37d093435a41f2aab8f13c19ba067d9776c90215f56614adad6ece597dbb34";
|
||||
};
|
||||
peertubeS3KeyConfig =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GK1f9feea9960f6f95ff404c9b";
|
||||
s3SecretKeyFile = pkgs.writeText "s3SecretKey" "7295c4201966a02c2c3d25b5cea4a5ff782966a2415e3a196f91924631191395";
|
||||
};
|
||||
pixelfedS3KeyConfig =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GKb5615457d44214411e673b7b";
|
||||
s3SecretKeyFile = pkgs.writeText "s3SecretKey" "5be6799a88ca9b9d813d1a806b64f15efa49482dbe15339ddfaf7f19cf434987";
|
||||
};
|
||||
in
|
||||
{
|
||||
fediversity = {
|
||||
garage.enable = true;
|
||||
pixelfed = pixelfedS3KeyConfig { inherit pkgs; };
|
||||
mastodon = mastodonS3KeyConfig { inherit pkgs; };
|
||||
peertube = peertubeS3KeyConfig { inherit pkgs; };
|
||||
};
|
||||
}
|
||||
159
launch/main.tf
Normal file
159
launch/main.tf
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
locals {
|
||||
system = "x86_64-linux"
|
||||
# dependency paths pre-calculated from npins
|
||||
pins = jsondecode(file("${path.root}/.npins.json"))
|
||||
# nix path: expose pins, use nixpkgs in flake commands (`nix run`)
|
||||
nix_path = "${join(":", [for name, path in local.pins : "${name}=${path}"])}:flake=${local.pins["nixpkgs"]}:flake"
|
||||
# user-facing applications
|
||||
application_configs = {
|
||||
# FIXME: wrap applications at the interface to grab them in one go?
|
||||
mastodon = {
|
||||
cfg = var.mastodon
|
||||
hostname = "test06"
|
||||
}
|
||||
pixelfed = {
|
||||
cfg = var.pixelfed
|
||||
hostname = "test04"
|
||||
}
|
||||
peertube = {
|
||||
cfg = var.peertube
|
||||
hostname = "test05"
|
||||
}
|
||||
}
|
||||
# services shared between applications
|
||||
peripherals = { for name, inst in {
|
||||
garage = "test01"
|
||||
} : name => {
|
||||
hostname = inst
|
||||
cfg = {
|
||||
# enable if any user applications are enabled
|
||||
enable = anytrue([for _, app in local.application_configs: app.cfg.enable])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# hash of our code directory, used in dev to trigger re-deploy
|
||||
# FIXME settle for pwd when in /nix/store?
|
||||
# FIXME calculate separately to reduce false positives
|
||||
data "external" "hash" {
|
||||
program = ["sh", "-c", "echo \"{\\\"hash\\\":\\\"$(nix-hash ..)\\\"}\""]
|
||||
}
|
||||
|
||||
# TF resource to build and deploy NixOS instances.
|
||||
resource "terraform_data" "nixos" {
|
||||
|
||||
for_each = {for name, inst in merge(
|
||||
local.peripherals,
|
||||
local.application_configs,
|
||||
) : name => inst if inst.cfg.enable}
|
||||
|
||||
# trigger rebuild/deploy if (FIXME?) any potentially used config/code changed,
|
||||
# preventing these (20+s, build being bottleneck) when nothing changed.
|
||||
# terraform-nixos separates these to only deploy if instantiate changed,
|
||||
# yet building even then - which may be not as bad using deploy on remote.
|
||||
# having build/deploy one resource reflects wanting to prevent no-op rebuilds
|
||||
# over preventing (with less false positives) no-op deployments,
|
||||
# as i could not find a way to do prevent no-op rebuilds without merging them:
|
||||
# - generic resources cannot have outputs, while we want info from the instantiation (unless built on host?).
|
||||
# - `data` always runs, which is slow for deploy and especially build.
|
||||
triggers_replace = [
|
||||
data.external.hash.result,
|
||||
var.domain,
|
||||
var.initialUser,
|
||||
local.system,
|
||||
each.key,
|
||||
each.value,
|
||||
]
|
||||
|
||||
provisioner "local-exec" {
|
||||
# directory to run the script from. we use the TF project root dir,
|
||||
# here as a path relative from where TF is run from.
|
||||
# note that absolute paths can cause false positives in triggers,
|
||||
# so are generally discouraged in TF.
|
||||
working_dir = path.root
|
||||
environment = {
|
||||
# nix path used on build, lets us refer to e.g. nixpkgs like `<nixpkgs>`
|
||||
NIX_PATH = local.nix_path
|
||||
}
|
||||
# TODO: refactor back to command="ignoreme" interpreter=concat([]) to protect sensitive data from error logs?
|
||||
# TODO: build on target?
|
||||
command = <<-EOF
|
||||
set -euo pipefail
|
||||
|
||||
# INSTANTIATE
|
||||
command=(
|
||||
nix-instantiate
|
||||
--expr
|
||||
'let
|
||||
os = import <nixpkgs/nixos> {
|
||||
system = "${local.system}";
|
||||
configuration = {
|
||||
# note interpolations here TF ones
|
||||
imports = [
|
||||
# shared NixOS config
|
||||
${path.root}/shared.nix
|
||||
# FIXME: separate template options by service
|
||||
${path.root}/options.nix
|
||||
# for service `mastodon` import `mastodon.nix`
|
||||
${path.root}/${each.key}.nix
|
||||
# FIXME: get VM details from TF
|
||||
${path.root}/../infra/test-machines/${each.value.hostname}
|
||||
];
|
||||
# nix path for debugging
|
||||
nix.nixPath = [ "${local.nix_path}" ];
|
||||
## FIXME: switch root authentication to users with password-less sudo, see #24
|
||||
users.users.root.openssh.authorizedKeys.keys = let
|
||||
keys = import ../keys;
|
||||
in attrValues keys.contributors ++ [
|
||||
# allow our panel vm access to the test machines
|
||||
keys.panel
|
||||
];
|
||||
} //
|
||||
# template parameters passed in from TF thru json
|
||||
builtins.fromJSON "${replace(jsonencode({
|
||||
terraform = {
|
||||
domain = var.domain
|
||||
hostname = each.value.hostname
|
||||
initialUser = var.initialUser
|
||||
}
|
||||
}), "\"", "\\\"")}";
|
||||
};
|
||||
in
|
||||
# info we want to get back out
|
||||
{
|
||||
substituters = builtins.concatStringsSep " " os.config.nix.settings.substituters;
|
||||
trusted_public_keys = builtins.concatStringsSep " " os.config.nix.settings.trusted-public-keys;
|
||||
drv_path = os.config.system.build.toplevel.drvPath;
|
||||
out_path = os.config.system.build.toplevel;
|
||||
}'
|
||||
)
|
||||
# instantiate the config in /nix/store
|
||||
"$${command[@]}" -A out_path
|
||||
# get the other info
|
||||
json="$("$${command[@]}" --eval --strict --json)"
|
||||
|
||||
# DEPLOY
|
||||
declare substituters trusted_public_keys drv_path
|
||||
# set our variables using the json object
|
||||
eval "export $(echo $json | jaq -r 'to_entries | map("\(.key)=\(.value)") | @sh')"
|
||||
# FIXME: de-hardcode domain
|
||||
host="root@${each.value.hostname}.abundos.eu" # FIXME: #24
|
||||
buildArgs=(
|
||||
--option extra-binary-caches https://cache.nixos.org/
|
||||
--option substituters $substituters
|
||||
--option trusted-public-keys $trusted_public_keys
|
||||
)
|
||||
sshOpts=(
|
||||
-o BatchMode=yes
|
||||
-o StrictHostKeyChecking=no
|
||||
)
|
||||
# get the realized derivation to deploy
|
||||
outPath=$(nix-store --realize "$drv_path" "$${buildArgs[@]}")
|
||||
# deploy the config by nix-copy-closure
|
||||
NIX_SSHOPTS="$${sshOpts[*]}" nix-copy-closure --to "$host" "$outPath" --gzip --use-substitutes
|
||||
# switch the remote host to the config
|
||||
ssh "$${sshOpts[@]}" "$host" "nix-env --profile /nix/var/nix/profiles/system --set $outPath; $outPath/bin/switch-to-configuration switch"
|
||||
EOF
|
||||
}
|
||||
}
|
||||
17
launch/mastodon.nix
Normal file
17
launch/mastodon.nix
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{ pkgs, ... }:
|
||||
let
|
||||
mastodonS3KeyConfig =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GK3515373e4c851ebaad366558";
|
||||
s3SecretKeyFile = pkgs.writeText "s3SecretKey" "7d37d093435a41f2aab8f13c19ba067d9776c90215f56614adad6ece597dbb34";
|
||||
};
|
||||
in
|
||||
{
|
||||
fediversity = {
|
||||
mastodon = mastodonS3KeyConfig { inherit pkgs; } // {
|
||||
enable = true;
|
||||
};
|
||||
temp.cores = 1; # FIXME: should come from NixOps4 eventually
|
||||
};
|
||||
}
|
||||
54
launch/options.nix
Normal file
54
launch/options.nix
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
# TODO: could (part of) this be generated somehow? c.f #275
|
||||
{
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib) types mkOption;
|
||||
inherit (types) str enum submodule;
|
||||
in
|
||||
{
|
||||
options.terraform = {
|
||||
domain = mkOption {
|
||||
type = enum [
|
||||
"fediversity.net"
|
||||
];
|
||||
description = ''
|
||||
Apex domain under which the services will be deployed.
|
||||
'';
|
||||
default = "fediversity.net";
|
||||
};
|
||||
hostname = mkOption {
|
||||
type = str;
|
||||
description = ''
|
||||
Internal name of the host, e.g. test01
|
||||
'';
|
||||
};
|
||||
initialUser = mkOption {
|
||||
description = ''
|
||||
Some services require an initial user to access them.
|
||||
This option sets the credentials for such an initial user.
|
||||
'';
|
||||
type = submodule {
|
||||
options = {
|
||||
displayName = mkOption {
|
||||
type = str;
|
||||
description = "Display name of the user";
|
||||
};
|
||||
username = mkOption {
|
||||
type = str;
|
||||
description = "Username for login";
|
||||
};
|
||||
email = mkOption {
|
||||
type = str;
|
||||
description = "User's email address";
|
||||
};
|
||||
password = mkOption {
|
||||
type = str;
|
||||
description = "Password for login";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
20
launch/peertube.nix
Normal file
20
launch/peertube.nix
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{ pkgs, ... }:
|
||||
let
|
||||
peertubeS3KeyConfig =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GK1f9feea9960f6f95ff404c9b";
|
||||
s3SecretKeyFile = pkgs.writeText "s3SecretKey" "7295c4201966a02c2c3d25b5cea4a5ff782966a2415e3a196f91924631191395";
|
||||
};
|
||||
in
|
||||
{
|
||||
fediversity = {
|
||||
peertube = peertubeS3KeyConfig { inherit pkgs; } // {
|
||||
enable = true;
|
||||
## NOTE: Only ever used for testing anyway.
|
||||
##
|
||||
## FIXME: Generate and store in NixOps4's state.
|
||||
secretsFile = pkgs.writeText "secret" "574e093907d1157ac0f8e760a6deb1035402003af5763135bae9cbd6abe32b24";
|
||||
};
|
||||
};
|
||||
}
|
||||
16
launch/pixelfed.nix
Normal file
16
launch/pixelfed.nix
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{ pkgs, ... }:
|
||||
let
|
||||
pixelfedS3KeyConfig =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GKb5615457d44214411e673b7b";
|
||||
s3SecretKeyFile = pkgs.writeText "s3SecretKey" "5be6799a88ca9b9d813d1a806b64f15efa49482dbe15339ddfaf7f19cf434987";
|
||||
};
|
||||
in
|
||||
{
|
||||
fediversity = {
|
||||
pixelfed = pixelfedS3KeyConfig { inherit pkgs; } // {
|
||||
enable = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
43
launch/resource.nix
Normal file
43
launch/resource.nix
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
{
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (lib) attrValues elem mkDefault;
|
||||
inherit (lib.attrsets) concatMapAttrs optionalAttrs;
|
||||
inherit (lib.strings) removeSuffix;
|
||||
|
||||
secretsPrefix = ../secrets;
|
||||
secrets = import (secretsPrefix + "/secrets.nix");
|
||||
keys = import ../keys;
|
||||
|
||||
in
|
||||
{
|
||||
fediversityVm.hostPublicKey = mkDefault keys.systems.${config.fediversityVm.name};
|
||||
|
||||
## The configuration of the machine. We strive to keep in this file only the
|
||||
## options that really need to be injected from the resource. Everything else
|
||||
## should go into the `./nixos` subdirectory.
|
||||
imports = [
|
||||
../infra/common/options.nix
|
||||
../infra/common/nixos
|
||||
];
|
||||
|
||||
## Read all the secrets, filter the ones that are supposed to be readable
|
||||
## with this host's public key, and add them correctly to the configuration
|
||||
## as `age.secrets.<name>.file`.
|
||||
age.secrets = concatMapAttrs (
|
||||
name: secret:
|
||||
optionalAttrs (elem config.fediversityVm.hostPublicKey secret.publicKeys) {
|
||||
${removeSuffix ".age" name}.file = secretsPrefix + "/${name}";
|
||||
}
|
||||
) secrets;
|
||||
|
||||
## FIXME: switch root authentication to users with password-less sudo, see #24
|
||||
users.users.root.openssh.authorizedKeys.keys = attrValues keys.contributors ++ [
|
||||
# allow our panel vm access to the test machines
|
||||
keys.panel
|
||||
];
|
||||
}
|
||||
26
launch/shared.nix
Normal file
26
launch/shared.nix
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (config.terraform) hostname domain initialUser;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
<disko/module.nix>
|
||||
<agenix/modules/age.nix>
|
||||
../services/fediversity
|
||||
./resource.nix
|
||||
];
|
||||
fediversityVm.name = hostname;
|
||||
fediversity = {
|
||||
inherit domain;
|
||||
temp.initialUser = {
|
||||
inherit (initialUser) username email displayName;
|
||||
# FIXME: disgusting, but nvm, this is going to be replaced by
|
||||
# proper central authentication at some point
|
||||
passwordFile = pkgs.writeText "password" initialUser.password;
|
||||
};
|
||||
};
|
||||
}
|
||||
1
launch/shell.nix
Normal file
1
launch/shell.nix
Normal file
|
|
@ -0,0 +1 @@
|
|||
(import ./. { }).shell
|
||||
26
launch/tests.nix
Normal file
26
launch/tests.nix
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{ lib, pkgs }:
|
||||
let
|
||||
defaults = {
|
||||
virtualisation = {
|
||||
memorySize = 2048;
|
||||
cores = 2;
|
||||
};
|
||||
};
|
||||
tf = pkgs.callPackage ./tf.nix { };
|
||||
tfEnv = pkgs.callPackage ./tf-env.nix { };
|
||||
in
|
||||
lib.mapAttrs (name: test: pkgs.testers.runNixOSTest (test // { inherit name; })) {
|
||||
tf-validate = {
|
||||
inherit defaults;
|
||||
nodes.server = {
|
||||
environment.systemPackages = [
|
||||
tf
|
||||
tfEnv
|
||||
];
|
||||
};
|
||||
testScript = ''
|
||||
server.wait_for_unit("multi-user.target")
|
||||
server.succeed("${lib.getExe tf} -chdir='${tfEnv}/launch' validate")
|
||||
'';
|
||||
};
|
||||
}
|
||||
34
launch/tf-env.nix
Normal file
34
launch/tf-env.nix
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
sources ? import ../npins,
|
||||
...
|
||||
}:
|
||||
pkgs.stdenv.mkDerivation {
|
||||
name = "tf-repo";
|
||||
src =
|
||||
with lib.fileset;
|
||||
toSource {
|
||||
root = ../.;
|
||||
# don't copy ignored files
|
||||
fileset = intersection (gitTracked ../.) ../.;
|
||||
};
|
||||
buildInputs = [
|
||||
(import ./tf.nix { inherit lib pkgs; })
|
||||
];
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
pushd launch/
|
||||
# calculated pins
|
||||
echo '${lib.strings.toJSON sources}' > .npins.json
|
||||
# generate TF lock for nix's TF providers
|
||||
tofu init -input=false
|
||||
popd
|
||||
runHook postBuild
|
||||
'';
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
cp -r . $out
|
||||
runHook postInstall
|
||||
'';
|
||||
}
|
||||
24
launch/tf.nix
Normal file
24
launch/tf.nix
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# FIXME: use overlays so this gets imported just once?
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
tofuProvider =
|
||||
provider:
|
||||
provider.override (oldArgs: {
|
||||
provider-source-address =
|
||||
lib.replaceStrings [ "https://registry.terraform.io/providers" ] [ "registry.opentofu.org" ]
|
||||
oldArgs.homepage;
|
||||
});
|
||||
tf = pkgs.opentofu;
|
||||
tfPlugins = (
|
||||
p: [
|
||||
p.external
|
||||
]
|
||||
);
|
||||
in
|
||||
# tf.withPlugins tfPlugins
|
||||
# https://github.com/NixOS/nixpkgs/pull/358522
|
||||
tf.withPlugins (p: pkgs.lib.lists.map tofuProvider (tfPlugins p))
|
||||
51
launch/variables.tf
Normal file
51
launch/variables.tf
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# TODO: (partially) generate, say from nix modules, c.f. #275
|
||||
|
||||
variable "domain" {
|
||||
type = string
|
||||
default = "fediversity.net"
|
||||
}
|
||||
|
||||
variable "mastodon" {
|
||||
type = object({
|
||||
enable = bool
|
||||
})
|
||||
default = {
|
||||
enable = false
|
||||
}
|
||||
}
|
||||
|
||||
variable "pixelfed" {
|
||||
type = object({
|
||||
enable = bool
|
||||
})
|
||||
default = {
|
||||
enable = false
|
||||
}
|
||||
}
|
||||
|
||||
variable "peertube" {
|
||||
type = object({
|
||||
enable = bool
|
||||
})
|
||||
default = {
|
||||
enable = false
|
||||
}
|
||||
}
|
||||
|
||||
variable "initialUser" {
|
||||
type = object({
|
||||
displayName = string
|
||||
username = string
|
||||
email = string
|
||||
# TODO: mark (nested) credentials as sensitive
|
||||
# https://discuss.hashicorp.com/t/is-it-possible-to-mark-an-attribute-of-an-object-as-sensitive/24649/2
|
||||
password = string
|
||||
})
|
||||
# FIXME: remove default when the form provides this value, see #285
|
||||
default = {
|
||||
displayName = "Testy McTestface"
|
||||
username = "test"
|
||||
email = "test@test.com"
|
||||
password = "testtest"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,47 @@
|
|||
{
|
||||
"pins": {
|
||||
"agenix": {
|
||||
"type": "Git",
|
||||
"repository": {
|
||||
"type": "GitHub",
|
||||
"owner": "ryantm",
|
||||
"repo": "agenix"
|
||||
},
|
||||
"branch": "main",
|
||||
"submodules": false,
|
||||
"revision": "e600439ec4c273cf11e06fe4d9d906fb98fa097c",
|
||||
"url": "https://github.com/ryantm/agenix/archive/e600439ec4c273cf11e06fe4d9d906fb98fa097c.tar.gz",
|
||||
"hash": "006ngydiykjgqs85cl19h9klq8kaqm5zs0ng51dnwy7nzgqxzsdr"
|
||||
},
|
||||
"disko": {
|
||||
"type": "GitRelease",
|
||||
"repository": {
|
||||
"type": "GitHub",
|
||||
"owner": "nix-community",
|
||||
"repo": "disko"
|
||||
},
|
||||
"pre_releases": false,
|
||||
"version_upper_bound": null,
|
||||
"release_prefix": null,
|
||||
"submodules": false,
|
||||
"version": "v1.11.0",
|
||||
"revision": "cdf8deded8813edfa6e65544f69fdd3a59fa2bb4",
|
||||
"url": "https://api.github.com/repos/nix-community/disko/tarball/v1.11.0",
|
||||
"hash": "13brimg7z7k9y36n4jc1pssqyw94nd8qvgfjv53z66lv4xkhin92"
|
||||
},
|
||||
"flake-inputs": {
|
||||
"type": "Git",
|
||||
"repository": {
|
||||
"type": "GitHub",
|
||||
"owner": "fricklerhandwerk",
|
||||
"repo": "flake-inputs"
|
||||
},
|
||||
"branch": "main",
|
||||
"submodules": false,
|
||||
"revision": "559574c9cbb8af262f3944b67d60fbf0f6ad03c3",
|
||||
"url": "https://github.com/fricklerhandwerk/flake-inputs/archive/559574c9cbb8af262f3944b67d60fbf0f6ad03c3.tar.gz",
|
||||
"hash": "0gbhmp6x2vdzvfnsvqzal3g8f8hx2ia6r73aibc78kazf78m67x6"
|
||||
},
|
||||
"htmx": {
|
||||
"type": "GitRelease",
|
||||
"repository": {
|
||||
|
|
|
|||
|
|
@ -12,21 +12,32 @@ let
|
|||
manage = pkgs.writeScriptBin "manage" ''
|
||||
exec ${pkgs.lib.getExe pkgs.python3} ${toString ./src/manage.py} $@
|
||||
'';
|
||||
package = pkgs.callPackage ./nix/package.nix { };
|
||||
in
|
||||
{
|
||||
shell = pkgs.mkShellNoCC {
|
||||
inputsFrom = [ (pkgs.callPackage ./nix/package.nix { }) ];
|
||||
inputsFrom = [ package ];
|
||||
packages = [
|
||||
pkgs.npins
|
||||
manage
|
||||
];
|
||||
env = import ./env.nix { inherit lib pkgs; } // {
|
||||
NPINS_DIRECTORY = toString ../npins;
|
||||
CREDENTIALS_DIRECTORY = toString ./.credentials;
|
||||
DATABASE_URL = "sqlite:///${toString ./src}/db.sqlite3";
|
||||
};
|
||||
env =
|
||||
let
|
||||
inherit (builtins) toString;
|
||||
in
|
||||
import ./env.nix { inherit lib pkgs; }
|
||||
// {
|
||||
NPINS_DIRECTORY = toString ../npins;
|
||||
CREDENTIALS_DIRECTORY = toString ./.credentials;
|
||||
DATABASE_URL = "sqlite:///${toString ./src}/db.sqlite3";
|
||||
# locally: use a fixed relative reference, so we can use our newest files without copying to the store
|
||||
REPO_DIR = toString ../.;
|
||||
};
|
||||
shellHook = ''
|
||||
ln -sf ${sources.htmx}/dist/htmx.js src/panel/static/htmx.min.js
|
||||
${lib.concatStringsSep "\n" (
|
||||
map (file: "ln -sf ${file.from} ${toString ./src/${file.to}}") package.generated
|
||||
)}
|
||||
|
||||
# in production, secrets are passed via CREDENTIALS_DIRECTORY by systemd.
|
||||
# use this directory for testing with local secrets
|
||||
mkdir -p $CREDENTIALS_DIRECTORY
|
||||
|
|
|
|||
|
|
@ -3,16 +3,14 @@
|
|||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (builtins) toString;
|
||||
in
|
||||
{
|
||||
REPO_DIR = toString ../.;
|
||||
# explicitly use nix, as e.g. lix does not have configurable-impure-env
|
||||
BIN_PATH = lib.makeBinPath [
|
||||
# explicitly use nix, as e.g. lix does not have configurable-impure-env
|
||||
pkgs.nix
|
||||
# nixops error maybe due to our flake git hook: executing 'git': No such file or directory
|
||||
pkgs.lix
|
||||
pkgs.bash
|
||||
pkgs.coreutils
|
||||
pkgs.openssh
|
||||
pkgs.git
|
||||
pkgs.jaq # tf
|
||||
(import ../launch/tf.nix { inherit lib pkgs; })
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ let
|
|||
((pkgs.formats.pythonVars { }).generate "settings.py" cfg.settings)
|
||||
(builtins.toFile "extra-settings.py" cfg.extra-settings)
|
||||
];
|
||||
REPO_DIR = import ../../launch/tf-env.nix { inherit lib pkgs; };
|
||||
};
|
||||
|
||||
python-environment = pkgs.python3.withPackages (
|
||||
|
|
@ -157,9 +158,7 @@ in
|
|||
};
|
||||
};
|
||||
|
||||
users.users.${name} = {
|
||||
isNormalUser = true;
|
||||
};
|
||||
users.users.${name}.isNormalUser = true;
|
||||
|
||||
users.groups.${name} = { };
|
||||
systemd.services.${name} = {
|
||||
|
|
@ -167,6 +166,7 @@ in
|
|||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
path = [
|
||||
pkgs.openssh
|
||||
python-environment
|
||||
manage-service
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
sqlite,
|
||||
python3,
|
||||
sources ? import ../../npins,
|
||||
|
|
@ -11,7 +12,7 @@ let
|
|||
root = ../src;
|
||||
fileset = intersection (gitTracked ../../.) ../src;
|
||||
};
|
||||
pyproject = with lib; fromTOML pyproject-toml;
|
||||
pyproject = fromTOML pyproject-toml;
|
||||
# TODO: define this globally
|
||||
name = "panel";
|
||||
# TODO: we may want this in a file so it's easier to read statically
|
||||
|
|
@ -25,6 +26,12 @@ let
|
|||
packages = [ "${name}" ]
|
||||
include-package-data = true
|
||||
'';
|
||||
generated = [
|
||||
{
|
||||
from = "${sources.htmx}/dist/htmx.min.js";
|
||||
to = "./panel/static/htmx.min.js";
|
||||
}
|
||||
];
|
||||
in
|
||||
python3.pkgs.buildPythonPackage {
|
||||
pname = name;
|
||||
|
|
@ -54,11 +61,19 @@ python3.pkgs.buildPythonPackage {
|
|||
]
|
||||
++ pythonPackages;
|
||||
|
||||
passthru = {
|
||||
inherit generated;
|
||||
};
|
||||
|
||||
postInstall = ''
|
||||
mkdir -p $out/bin
|
||||
cp -v ${src}/manage.py $out/bin/manage.py
|
||||
chmod +x $out/bin/manage.py
|
||||
wrapProgram $out/bin/manage.py --prefix PYTHONPATH : "$PYTHONPATH"
|
||||
cp ${sources.htmx}/dist/htmx.min.js* $out/${python3.sitePackages}/panel/static/
|
||||
wrapProgram $out/bin/manage.py \
|
||||
--set REPO_DIR "${import ../../launch/tf-env.nix { inherit lib pkgs; }}" \
|
||||
--prefix PYTHONPATH : "$PYTHONPATH"
|
||||
${lib.concatStringsSep "\n" (
|
||||
map (file: "cp ${file.from} $out/${python3.sitePackages}/${file.to}") generated
|
||||
)}
|
||||
'';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# TODO upstream, see #248
|
||||
{
|
||||
lib,
|
||||
buildPythonPackage,
|
||||
|
|
|
|||
|
|
@ -171,6 +171,53 @@ COMPRESS_PRECOMPILERS = [
|
|||
|
||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||
|
||||
LOGGING = {
|
||||
"version": 1,
|
||||
"disable_existing_loggers": False,
|
||||
"filters": {
|
||||
"require_debug_false": {
|
||||
"()": "django.utils.log.RequireDebugFalse",
|
||||
},
|
||||
"require_debug_true": {
|
||||
"()": "django.utils.log.RequireDebugTrue",
|
||||
},
|
||||
},
|
||||
"formatters": {
|
||||
"django.server": {
|
||||
"()": "django.utils.log.ServerFormatter",
|
||||
"format": "[{server_time}] {message}",
|
||||
"style": "{",
|
||||
},
|
||||
"standard": {
|
||||
"format": "%(asctime)s [%(levelname)s] %(name)s: %(message)s"
|
||||
},
|
||||
},
|
||||
"handlers": {
|
||||
"console": {
|
||||
"level": "INFO",
|
||||
# "filters": ["require_debug_true"],
|
||||
"class": "logging.StreamHandler",
|
||||
"formatter": "standard",
|
||||
},
|
||||
"django.server": {
|
||||
"level": "INFO",
|
||||
"class": "logging.StreamHandler",
|
||||
"formatter": "django.server",
|
||||
},
|
||||
"mail_admins": {
|
||||
"level": "ERROR",
|
||||
"filters": ["require_debug_false"],
|
||||
"class": "django.utils.log.AdminEmailHandler",
|
||||
},
|
||||
},
|
||||
"loggers": {
|
||||
"": {
|
||||
"handlers": ["console"],
|
||||
"level": "DEBUG" if DEBUG else "INFO",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
# Customization via user settings
|
||||
# This must be at the end, as it must be able to override the above
|
||||
# TODO(@fricklerhandwerk):
|
||||
|
|
|
|||
1
panel/src/panel/static/htmx.min.js
vendored
1
panel/src/panel/static/htmx.min.js
vendored
|
|
@ -1 +0,0 @@
|
|||
/nix/store/mwqqk0qmldzvv4xj9kq2lbah2flhc44z-source/dist/htmx.js
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
from enum import Enum
|
||||
import json
|
||||
import subprocess
|
||||
import logging
|
||||
import os
|
||||
|
||||
from django.urls import reverse_lazy
|
||||
|
|
@ -13,6 +14,8 @@ from django.shortcuts import render
|
|||
from panel import models, settings
|
||||
from panel.configuration import forms
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Index(TemplateView):
|
||||
template_name = 'index.html'
|
||||
|
|
@ -134,25 +137,26 @@ class DeploymentStatus(ConfigurationForm):
|
|||
},
|
||||
}
|
||||
# serialize back and forth now we still need to manually inject the dummy user
|
||||
deployment_params = json.dumps(dummy_user | json.loads(submission))
|
||||
deployment_params = dummy_user | json.loads(submission)
|
||||
env = {
|
||||
"PATH": settings.bin_path,
|
||||
# "TF_LOG": "info",
|
||||
} | {
|
||||
# pass in form info to our deployment
|
||||
"DEPLOYMENT": deployment_params,
|
||||
# FIXME: ensure sensitive info is protected
|
||||
f"TF_VAR_{k}": v if isinstance(v, str) else json.dumps(v) for k, v in deployment_params.items()
|
||||
}
|
||||
logger.info("env: %s", env)
|
||||
cwd = f"{settings.repo_dir}/launch"
|
||||
cmd = [
|
||||
"nix",
|
||||
"develop",
|
||||
"--extra-experimental-features",
|
||||
"configurable-impure-env",
|
||||
"--command",
|
||||
"nixops4",
|
||||
"tofu",
|
||||
# f"-chdir={cwd}",
|
||||
"apply",
|
||||
"test",
|
||||
f"-state={cwd}/terraform.tfstate", # FIXME: separate users' state
|
||||
"--auto-approve",
|
||||
"-lock=false",
|
||||
"-parallelism=1" # limit OOM risk
|
||||
]
|
||||
deployment_result = subprocess.run(
|
||||
cmd,
|
||||
cwd=settings.repo_dir,
|
||||
env=env,
|
||||
)
|
||||
return deployment_result, json.loads(deployment_params)
|
||||
deployment_result = subprocess.run(cmd, cwd=cwd, env=env)
|
||||
logger.debug("deployment_result: %s", deployment_result)
|
||||
return deployment_result, deployment_params
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
age-encryption.org/v1
|
||||
-> ssh-ed25519 Jpc21A JzLWMEH98I5/A8O55mKUMy5zo2kg3Qk8SfXnHvkjwT4
|
||||
8f7zDHSp3AHoAQy0dVWMa1TurCBLnsHNtbNjaD++7ow
|
||||
-> ssh-ed25519 BAs8QA eCD3saYXdv1bjAoQghmyVqHjMBu/o2lWgu7grk1vgRs
|
||||
//pOnkzqQTK3xmeCjruo46ju2X136KEt6DpsegMouFQ
|
||||
-> ssh-ed25519 ofQnlg ePjq7GmM36qaGxcJ0qnW8FdKDjwlXtFqOBK8OgWY3Co
|
||||
gVmsDP9rMcQD/B6BpNhCn+avdgjhyyohNUXlatXpXo0
|
||||
-> ssh-ed25519 COspvA lrQB/NEmMUR2RWxfRzE2iTDkjMYsrIaiKn8thxZR+RA
|
||||
MU23Z28v+cNk2VxpAYaYoFb53js2Zr9/KAM9uMe6+EA
|
||||
-> ssh-ed25519 2XrTgw z1ixx5dYCNbgw6wWV45b4wn69X/5/4MzesTomWa4WB4
|
||||
eNSlP6+nUW9rpsGyzqOEQ+7IVpGeU3UcZpyfB9XT2/4
|
||||
-> ssh-ed25519 1MUEqQ c6ps9RB6Dw9JtR0+4eB1NDx44uUes8YjLrY7RCpD0jg
|
||||
GwVRqR5t07ctbWhwH76T+SAe2Y6Vv1uY/AHkzd/gw/c
|
||||
-> ssh-ed25519 Fa25Dw jTqtV2RWsXBH4zgWAYr9tBGC/BbXKBvr3uyL8IgmI1o
|
||||
qBirnzIpi9hB61xwyS+5U6XBobAquEJrV3cleDtG8/4
|
||||
--- j/vJgDV+47UmKokdvztXntBIhCLEyUm2aYoGJ2WMKbU
|
||||
¢¹ŽÀi‹±ËQõf §¥ÐÅ·DN§àB"—ÍvsëB6PùQžorF‡<46>Å
|
||||
-> ssh-ed25519 Jpc21A 9edPaA2tT4SeYNTPzF0E157daC2o+JH/WQQCT+vLbFg
|
||||
C48EtLdhB75TTzfEZTw1DypicHiVlSmFzjfbqfO9N/8
|
||||
-> ssh-ed25519 BAs8QA T+kXpZg1v0XRkub5DWir7vYwO7KaOJLZBNYxxXiBUCw
|
||||
zBRwMTDpyI7twEwUGsmJYyYPw9btBx5Kakj1yT+XY8U
|
||||
-> ssh-ed25519 ofQnlg 4UoEDY/tdKz8LrX1BkBU1/cn+vSaYLUl7xX9YmzANBY
|
||||
8CACq1n3AJgD9IyPN23iRvThqsfQFF5+jmkKnhun24U
|
||||
-> ssh-ed25519 COspvA HxcbkqHL+LpVmwb+Fo5JuUU+C+Pxzdxtb0yZHixwuzM
|
||||
7FIhxdbjHJlgQQgjrHHUK5cecqs5aT7X3I8TWf8c2gc
|
||||
-> ssh-ed25519 2XrTgw R6Ia8MVIZKPnNZ0rspZ34EqoY8fOLeB9H7vnvNBLg1g
|
||||
55NUqz5Yygt6FKJ3bR5iHxQp8G7S2gyFwrJNX1Pb/2Y
|
||||
-> ssh-ed25519 awJeHA hJdTuAScoewVMt7HWiisSkL0zSeClFzYzzKL84G893o
|
||||
ou780VLrW1s4d6L+lEVu3kXaGn4dvtFPA31supwEL50
|
||||
-> ssh-ed25519 Fa25Dw mJcqnXA3fQeoKrG7RJ7nVeLxPvrxqbj+lJdx6jQ9IR8
|
||||
f5Q7mrQSSDsm1Z/uSAnvx66mgnRC3XaBLQrVL9f/Ijs
|
||||
--- W/KmboXTLV12X6WtVQKHNe+ZHvS2q9EHUZwofSgJSE8
|
||||
^kûÚ h©0ÔkÇ ¢¸_Ç·ûQÞm‘’7\òÖ}÷Áë?½qø‚<ÿm
|
||||
|
|
@ -1,17 +1,18 @@
|
|||
age-encryption.org/v1
|
||||
-> ssh-ed25519 Jpc21A l6Xwv4JBlTeRTC7RgjxY9gDrCk96atMUH/62P+u55Qs
|
||||
CrYsLZgDFAiR8up87lhGZqsbAEZtOXG+l5IzLh2uaqg
|
||||
-> ssh-ed25519 BAs8QA lgtmfoc4vKfRpI/XbIS258BMyIB4mTdquEx/Kxm5OTI
|
||||
3gQL8Rnqc7JfqsRmKYU3rD0cWMKdnIeVXbY3eFM07RU
|
||||
-> ssh-ed25519 ofQnlg 0vwuCrduMLjssA3CK3gfVPMSPYKO9cF7HH1JF/oJv18
|
||||
2KrZgQmpvw/tNDJrDArinnbEjopkkmuG8s7t6klBXcQ
|
||||
-> ssh-ed25519 COspvA NT+/h2KsiZN2XbaWAlrTlDwyAPmHWrwgr6f0uhSbEGs
|
||||
QpoAd+69VYrZwAC0LwDm1m/zfslVgzxpVFihQWDcqzE
|
||||
-> ssh-ed25519 2XrTgw QoJ/74FOqYFxHJYXJEkyzbGY0xptSjorNvnyUS1p6zk
|
||||
0sJ2F6IFuTrRvXO5ND1QL4CZ2lr1BAU3iQffC6Uc3h4
|
||||
-> ssh-ed25519 1MUEqQ xxgEUIhvWN/ZfRMGfu3fKQ+fWM5WSz8OexXPm6jaXDk
|
||||
RXe0JMZ0sYMdQvrbi+zAs9F3d98ocRFnsSGUuUWccRk
|
||||
-> ssh-ed25519 Fa25Dw tw4sqQcO86Gh0FGUD+O3bJ+8OcaN5rm8R6qocXvDbRg
|
||||
7hiWa4qznHTV45kvC7ucj7j7FbPrqYK5OcCcByrcSxg
|
||||
--- kvZDYq5n/OXu7xe2Kf5vGN0zosl9fgH4CAf3K0Tq3U4
|
||||
¤D!´Ój]2ï‹ÝƒT+•
ÃUó¬æcgÝoP”‰ ˆF.Þ¿_vbÕÓÔdª9
|
||||
-> ssh-ed25519 Jpc21A ZyJtpgzBrA3WFa1+uiNLZieP6GAqYzAtjmUkgbqKwyA
|
||||
TeO/ghRNVJQrdeFAvgQITC6MC7x7IHDtFYqHVloVfAQ
|
||||
-> ssh-ed25519 BAs8QA zIfPuCmSZyosDfWvL6A5DstWeBORDkjqb6Hxjx2dYgE
|
||||
Nq/YU6oDlIC+ROtM2P5aBeF6iJsxUbrU2LnLDRux35Y
|
||||
-> ssh-ed25519 ofQnlg dm1bj8BJxD1MpFqdDkfDL4wWV7mjmb51hVqkk2uRfwE
|
||||
N7Bwhw1agAbNGaF57VmFKwIWeUibaYRSu2Ke1ZlXPLQ
|
||||
-> ssh-ed25519 COspvA /DYoVVG4SOFgrIbMvEP0U7QpX6VK9otJVBYrj4I0dlo
|
||||
5EWys6IcMgrwW2p5fFeJEgDqandyiS1RzMvqGsN1X0I
|
||||
-> ssh-ed25519 2XrTgw YW5gzijsL1oRa5vQ3PY+8o3iNZIji1BZfB9dGcg9QHA
|
||||
0WWu3F1Rpo9mi4YU2r3Jydr6Fg7bqWMuTtMJOEOj3NU
|
||||
-> ssh-ed25519 awJeHA 8xl0RpXAJ7X5pe6qzDKXHJvMnjYEN85BS+maFytsSDQ
|
||||
MQYrdbh7w7TwGk2Wivja8acQYkmYZ2YWMkE/YA/5K3g
|
||||
-> ssh-ed25519 Fa25Dw koR3KjKzS3Uei58I68qYkgxE0ifhIXKTblpD4cFAVhQ
|
||||
X7mQgsMY02VHyxJUVN5ml/QRVTjBDm7BD4w0g3Jwmq4
|
||||
--- E6iHgNV3cjQrhNcZa6uqUwvGxf0ouNZpPXhet3Vicrw
|
||||
…ïò”F
Q/Gíù°Ê¤T]‘ns&[›ýëú&œæ
|
||||
Q(6pòM$È™ü Çõ
|
||||
|
|
@ -1,16 +1,15 @@
|
|||
age-encryption.org/v1
|
||||
-> ssh-ed25519 Jpc21A 7QzPABl0IuQlZ9nsqfdbmWT9zb6iHGEOQiJ5sBpuLWU
|
||||
zusphKpt0yVxQj0zh4AGtYFORIhUoJHJBYfEAHb/VN0
|
||||
-> ssh-ed25519 BAs8QA PBfmSc0pag5zCqB/EKvirDXyleNi2sgMZ0xTAMiANFo
|
||||
gugtjl9TSsGQuPypQiKZZqr7JfMKSdwVHGGKevyfF+k
|
||||
-> ssh-ed25519 ofQnlg RQd9jPyn8nv1zCLbETa9/JB39fwX3X0X9gElcHWEfCA
|
||||
7ZEBE4qaZUtrXLc0caZ/tfJFYT9UDYkVvuaBc0SVBhc
|
||||
-> ssh-ed25519 COspvA plM6PJykVR0NuSrOkRkA6ucOzUpijFaKbe99jaVrQSw
|
||||
7AkcdijjOSckx3GxXwXo1K34ReU3x0yWamlxdaA1FWA
|
||||
-> ssh-ed25519 2XrTgw +2ZOwvZRUmnuHVV8poyMR6eIvPQoxWQRngKJdL2kVHc
|
||||
rzWJIuZUtuurvIdV/47N2CNu8x4T/vca8IeRqi+mk/I
|
||||
-> ssh-ed25519 1MUEqQ 9U13b5LO4pSKhlvWEtkdrjTmVO5oGqcdT3Ime1AHjH4
|
||||
8wC87WZZYMZaR2YlG3oEt79QcZMA86TrUbvTekAUkqw
|
||||
--- X8Szdu5EyyPKR6xaL/8uKdHRc/D7wVGizk5k0XanreQ
|
||||
¯<EFBFBD>欿Æj{Ò“¦!q-ò˜G:£ÂjQò[_Ä„=ò<>#ÇŸd¾(i@/f3º’n°¦ý
|
||||
r :Ú‰ ¾×tx–ð¬|<<øX¡ÜºÊ¼™¨
|
||||
-> ssh-ed25519 Jpc21A N/T7HaInZ13IlJfzeli5nRz5pdBQETO6D1P8X42IHRw
|
||||
q431ZtsodQ9NgcWTjmS0Kx4ATwVFp2nkm+MHe7aXTZU
|
||||
-> ssh-ed25519 BAs8QA +VUHgmz2oNG6L1FgZy3uGVMs6qUGirFHK8Ts2ghNLHs
|
||||
sjQu78xqM6KLmRiYd2o2uK/PjYLnyZihzVoCV7qKBX4
|
||||
-> ssh-ed25519 ofQnlg cBfd95Ir33ggt1J1P2TkFRULr2uYPVuyrQ5XpjBxEW0
|
||||
TWFVHboXr95cFm5yjQ7gn7hjbSmVBfB/9dldsoga/9Q
|
||||
-> ssh-ed25519 COspvA RMW9FlDmiQUu7cg0fKir55VqrDRCoYVVZMOcMHyrMj8
|
||||
qeXkWdKFJN7APgYh7AjyJLeQI2CAEaGAcXiVaBaOJwY
|
||||
-> ssh-ed25519 2XrTgw BRobowRWZ9giVL2dFyGvzzF7gyWUQd1ounMQBtsM/lM
|
||||
dFyli2skTgzVWGVolLG2GuGNh/Xu3IaJsznOkcWqKGc
|
||||
-> ssh-ed25519 awJeHA Cu7fiv+SL71oho/xoJMw/Lztf4WkNKmImVS/8xyLiTo
|
||||
3sB/t0squi1crjHFBaN6btrvGUeWaKfmGa7yxREvy2o
|
||||
--- SqPDTJ/XV26nNG1ib5phNNRdQi5+Wk0cxhqUr1ygjGw
|
||||
Æt”OÊá<C3A1>âåYöª¶^´Iõ×U<C397>j†ë!k‹Y.<2E>^<5E>}Xúôæ¡3¿ÖŽ"kE×íšú¾‹s¥,0l+¾ýn‡;fW®‹
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
age-encryption.org/v1
|
||||
-> ssh-ed25519 Jpc21A fBhVzGFs61K63QtA8RdOuuGfHFjMe/Dp0M6TXGLGWDU
|
||||
qppnUZ+LQCXhuMCFMYv2D2CkmEfjb7mpmJufIeVjjaM
|
||||
-> ssh-ed25519 BAs8QA PNicZCWLkbvM4ih77/F4z6FzHomL9EsJCuSCjbdRTwA
|
||||
qIpTl/v7Xl08qBB//dFeW9qQiZg10YrYLnfyQrgDRfQ
|
||||
-> ssh-ed25519 ofQnlg 9/vSN3V25ysXBOvS4UJQEzm0734zqO0gXjhgzX63tTs
|
||||
AH9Q1lWr+RgICfW3h+D2SgCTFr+azI0x3J3eFnaz/XA
|
||||
-> ssh-ed25519 COspvA IB1nWOMaVZVcvEog6UaqCak2fcKxIUN2yXvvRSTDxGw
|
||||
Ti7JuBgU6phlI+oXfDDvx42dRu95kTwesRUKu4QsXZ4
|
||||
-> ssh-ed25519 2XrTgw 7S9ZhJvUFMw9tDCc0HvkRsRqjvmn47GFGVg/jkxIy1I
|
||||
cj27gqqihSZG3Jcab9h9FyNJ1J8FjlUiyVlDot+sbWQ
|
||||
-> ssh-ed25519 1MUEqQ l9mVTLD9rZXisBEz0sU2AdFNrJQ/+zuFTiIod5R/HCI
|
||||
2q3csSEvMW5vtzqGHYTtZ1nZ0J1vT23bjhuj9HTsdWk
|
||||
-> ssh-ed25519 kXy85Q BCrDvkPZLvx2Kvgapa3BT+AmpS6Fa5kpkgBnRVso2BE
|
||||
ZBi+x/2ilJIzhzGipdZQJoGOjSqCuAttsqCDVFlYJ8Y
|
||||
--- iWtseKyfUMBkQTUl9QzwXXLQcodEJeZt1Wuj5sR18yY
|
||||
+2,エ ゚恝Jrメィ>ア<7F>z?ホi<EFBE8E><69>ェ<EFBFBD>x<EFBFBD>0z<30>ヤ智メ劬呱^ゥネコ食・濤礫+1」ァ<EFBDA3>
|
||||
-> ssh-ed25519 Jpc21A 98RNGhrNW+Pg5EeQ6wOgRNaPqauBrI0hnUGDyCpFsQ4
|
||||
5ZCq4vkp6N9/KR4Uf0e9MtNM1SHD3Pr97B31or6y8Xc
|
||||
-> ssh-ed25519 BAs8QA znlRV7zbTUMsnDY/TiNgeCaqzi87jL/r/5dhc7bJ7hw
|
||||
9pwl5mcmbHaO39jmiuOkaC9mpyiS3xQSCd7q17gH6OU
|
||||
-> ssh-ed25519 ofQnlg Wr8M7IpBjvNatOlfmRodoHicPjSjyMVqkC+R+18SYjk
|
||||
Th18PUYoo1TvP+d+6aXLvipsm3QPW+DKQSv8rJqeblk
|
||||
-> ssh-ed25519 COspvA spxBYfEWDeKhaSsufZ4GDtIMKz8XznD4kS7Zjb4BLFU
|
||||
B2wT7+bXgWezmUIj0mpVPPjKOoIj7cDH16uvW4ujbss
|
||||
-> ssh-ed25519 2XrTgw lY+t4jvdSgZ5ZKMemAN0u32fPUAraaGu+ExMEsR/c0w
|
||||
KfOBcGrhIztEnKKmsv6ZD6K9TleZRgIRWbOlG8Tcvaw
|
||||
-> ssh-ed25519 awJeHA 1VVLZa0l8LX79LqZqlYRfXmKVIi9zpLcoysi0NQ3L0o
|
||||
m79gHUkQ87zFoB8Awlcxt2GrCMrwr5KSfyiSqa6kEko
|
||||
-> ssh-ed25519 kXy85Q uaEXsQeApgXqzWZRL0AtsPqjt5qOWxoQjN1Keiii1Ds
|
||||
LtHUNkV3n/jgeAcEIyq03z84KKa5qQoAo1aaJeK6Duk
|
||||
--- 6s4nA95ds+3slR3QtHQmAkTEBNlSOQusQzjaY/3M5Ds
|
||||
tÑ:ƒX‚´¯=χ´ù8€OoùxþÔ;ì“ÀyIý²ˆµÌˆõêJ/oW0Ô¼; x–$£tŠœ‡,7£-aý
|
||||
Binary file not shown.
|
|
@ -1,18 +1,18 @@
|
|||
age-encryption.org/v1
|
||||
-> ssh-ed25519 Jpc21A BfHJN3vILbsfY91kEjSQ+STrn6vQfn83Fx3cBCNshRQ
|
||||
0O8GJYfF8WFS4Xsgj5v1cly4JP1MgSN40OgRdW/i0rA
|
||||
-> ssh-ed25519 BAs8QA Ue0NLMpmZDSTGvwZ8lhzes7pcmit9F6uwzeT4XhiwC0
|
||||
jsvvuOW344i8GR4B139SX0LwTqzKQEgBvsy8oRppqBU
|
||||
-> ssh-ed25519 ofQnlg 9iSMQeTJn1OUqTF+M2sHpp69lblb8E6TVbgZs7vgD2U
|
||||
uMQI1gTTMvYW7ea9xBAln118JEeNvv3nqbq32zJoat8
|
||||
-> ssh-ed25519 COspvA YxCyfe0li23JoI2q4XFVUx4vrWApLwSnJD31PHXuPBg
|
||||
8xuT9+W2mnTag9tm6F6LXzHkIh2Nou/8lgxd64OpvWk
|
||||
-> ssh-ed25519 2XrTgw jEzw0A9Wd1b1Zoryzp/W/QZ6bd99E7sySnr/W2xcnDs
|
||||
IyMrojJ3AChS6lhj599caNM+02i16qtpc6cocln14b4
|
||||
-> ssh-ed25519 1MUEqQ haiI/5EkuTZ2YHxsqSVlqfM0VVR24DIDrMS3RmXwAhU
|
||||
qVIAvLp2qG4A3f3OKUqAKqH1eOicJz54nfblPSUKrSw
|
||||
-> ssh-ed25519 dgBsjw /vCnznu73U99onCWcM0aQlW0azscyUe4BB2kKeZvtHs
|
||||
MPnvXR/WVsl/tJ1YPoc7nk2Ls2x9bbtJdNp3CQTuuWI
|
||||
--- OzkqKlw4xu3McMk20orQN0h+VPYfUUSDC+DsgRU1tSw
|
||||
ü^@ÃmŽÚé`B˜³#{¡Ÿ‚ GUu´‹|¹Á œ¡ rÚïjb¥:Ô“d²ù] GØÎ©¦ú²-«Â–MÁ³ŸÜálÙ3mÌí)½š@¢—±e?¯ªêe¤üZ
|
||||
Y}ÿ!fÐ
|
||||
-> ssh-ed25519 Jpc21A EuMYAiZX+4A12eu19mIY7u+WYF7NJ9qJosQSVlxR6n8
|
||||
bK5CMXAmP23t1p9bgmqoVg4Qcu2qYKGc4t36v8e9eow
|
||||
-> ssh-ed25519 BAs8QA IwRyitDNTzUPzQAUbDNEKjFiF8WPD/OyztOZQeoTEzw
|
||||
OwiTWvk4NmUgExav0uH6HlThDNU5hsKXfR6KHsFOV3I
|
||||
-> ssh-ed25519 ofQnlg 3TcMbLX1JsQL8+Gqy7IFZwykZr2BspvPCuZT1SHtnQQ
|
||||
Ci5OeBj2aiC8ut9jIEUMt3qfYH+cJrnVud6AH54Ndn8
|
||||
-> ssh-ed25519 COspvA 0t9f3Wu3ILv4QTJhwT619y+7XFrryCLbpIZC6aE+qQI
|
||||
oPQP48F6oO/tkqLZDdjkGtIap7KHiAknbpTNL6/yLaU
|
||||
-> ssh-ed25519 2XrTgw YOZsaYQH9vMH0QqSXGh8GyhRV4MbcBGPFfFaKpo3Ckk
|
||||
kUShJbADA+6bpx2adxvzlI/0jSM5bIBfZfdSE/7Vm5Y
|
||||
-> ssh-ed25519 awJeHA dF3m0hQWX9c0EezDr56Kt/F4d1Uim7NwvIX6zRws0Eo
|
||||
pst243yrARODwrnyz8cJAzgDxdPOUsRbs7yPZePABFs
|
||||
-> ssh-ed25519 dgBsjw PUYHcP/tgNnKyvlIoJRcNcW3zabVV1iHXIWfKqgW9xc
|
||||
tXNjSuVH/g/oN5o75FPkFFpviF7SeFSN9kbqURvgMDE
|
||||
--- wHgBAN9c6F6T5hFJGo8uH8zqDkQDwx3/jVNKUtQ3arE
|
||||
«Ñ¢Á
|
||||
ò@µú¡fÃ`m;ÕcæäU²€ùò£Íd…eS’èyfv¿»¡€J?ø `œfj£Äa}lÃó ¿Úxç²BÇt2èfìôm08ÓoÝtRál9˜èx¤¢ŒÅž›æ÷
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
age-encryption.org/v1
|
||||
-> ssh-ed25519 Jpc21A RFzPu3fD28STex7ND5lE9bfCxQq/xeHEb7h7BFt9pVA
|
||||
8K+ECDGs71V91jEVQjrRVQNbdTzBb6W9jkp0+K1trzw
|
||||
-> ssh-ed25519 BAs8QA F2L9Eh9OItaPfAcR4qNnOQnvCyTeGdR5lSu0WqXiuU0
|
||||
3jLlt4qAL3/VKyfbP7R0/7SUwwPpWf5YUWwzjDONEy8
|
||||
-> ssh-ed25519 ofQnlg BLdBNuJExNlYED/XFU5zmYPtO1bxumuyPPgcs8qSLEY
|
||||
wIi31st4WS9O2a7VJmYpE8PimgzLvwU6zWkvHCy84yQ
|
||||
-> ssh-ed25519 COspvA GmC8YZVv3ZwidaDKUkLhx0l8UOmRw5ZBiM8r4/Ub7xA
|
||||
wK994Zs1aLspqY84Ik77qdMaEsjs0ZFNuKQDOGXsnmM
|
||||
-> ssh-ed25519 2XrTgw s62q7KOHZRqimCTwazX9LUvnpcYuzxwflumXe6NVF38
|
||||
WnOpHI9ejvRrZrQuasTEYyqP8ny3Hx9Q9bJzbK0pOI4
|
||||
-> ssh-ed25519 1MUEqQ 9NLHR5OwOngiLRguTkf5KnUHrc80mambCw19dPPKPQ8
|
||||
GDg9yRoRUaP1KOa/pOCFiLCCAxuFsuCIiDP/ERl8YLA
|
||||
-> ssh-ed25519 dgBsjw NulCMPtc2miJlHYpXMjQHUlc/HIaX4AqzxXZxt8cWkE
|
||||
tCh3WD91A89258F8THeddXvab77tTIjNjGxYNDVoaBQ
|
||||
--- oIUm35maOqmHL0nifKpyEvLpHSKmthxIT5DDueCVZDc
|
||||
ÈaT~œú£Úôf4÷„Ô$\—ì;¿@Äý`¦<18>(<28>3{VWgM}#<1A>ï9aû6¢½ª^öúT6éÞ!Þ %¿
|
||||
-> ssh-ed25519 Jpc21A TUGMeCK5ZehSdtfH2xpEEvMp4jZxJ2fTogXSkcf6blg
|
||||
BY6cKeB3MV84KvYThJsU0TSW5kMUJpbVVvccVtwtEIg
|
||||
-> ssh-ed25519 BAs8QA 9LgEP0N4MF4uEXLXGWRLgJzC9llYpKiP2lwAgN0ObxA
|
||||
cOI90Sc2ORgvFZD2I+oYcRa1Y47X2tuvFFqqKFo78nk
|
||||
-> ssh-ed25519 ofQnlg LYTsntB2zI1EJ8yyYOH6BvHXEOv+zX7QYrd7leXPeDA
|
||||
uqhuPl2udjxDMIdMd88xpQuAZ/QMXSLgxOeOhHyTjW8
|
||||
-> ssh-ed25519 COspvA geel/7vCPHmBT6Sg0bTqeUV4rA/i6w0NvFjGk8rF/VA
|
||||
8eIF+oWuM+16j1n//ndImjTPxPYqZ56WA8K5uybMbTo
|
||||
-> ssh-ed25519 2XrTgw uCKoYMidpNwfo2YDb2jyjONZvExK2wrZXXvv+ywrCCA
|
||||
X0E+2LuftCF3oAHp8z18WRZePAYt6tEYjnNAgMmfUNo
|
||||
-> ssh-ed25519 awJeHA 4cTdqU2X1gXyFxMHGHPgUq9g8XUM8sgbNa/NMl2GZmI
|
||||
J7cWCuKrf+r/nE0FjGj/DQDv7hBqbn0NidjY2m1mwGw
|
||||
-> ssh-ed25519 dgBsjw gyI/oiqvAzqxtism9yCygXYLZzCynTdAlPBcwZhryCw
|
||||
pKCMRUv6dsH/cS2Tm/gU0mxH6TsF6UGj0Fx4BNvYv9o
|
||||
--- MBLz1UcLi1SCQ2+tA1Zmv+2ZEiw0Ag2C4/gk7lzqJ0Q
|
||||
Ú<EFBFBD>©ËƒŽ£Ð Ó1–ÁÞ™òȲ=HK€Ÿ?G §g=R!Ì”2›t+Ü€!“ɈUGÞ¶±ïôM°?ö<02>OÉÀÅÊ
|
||||
|
|
@ -1,18 +1,17 @@
|
|||
age-encryption.org/v1
|
||||
-> ssh-ed25519 Jpc21A yazxa1xfjFav7HWIvegBhcLIaYnQw4noH+2d9VqyCk8
|
||||
LWgk9DdjH5ktQN0A9RVQN8PB2LlXsEVihwJpU4AFHDY
|
||||
-> ssh-ed25519 BAs8QA XnRG+IYDe3WOBNeNXF4KGCHGVtZg3T2kXJtwmVABjVw
|
||||
dfJcTZmDfL/2KuE0XRgO2UYlssaY0T2beTqUTKinhos
|
||||
-> ssh-ed25519 ofQnlg bVBe7VBynJr7wdVWajiKlVkAogJCsFE+NkVQcOFV3w0
|
||||
AUnc6BwNS2YPz1qFBkDGaXlEp+VzlceGllLctHhq1HM
|
||||
-> ssh-ed25519 COspvA dEY4MqMIfidzNBe9tUMZTpJNwYNlq+ngp+RLNEWN4Vg
|
||||
P+Yf/6NAoIFCfKOd4ykDiY62G/3TTk4jtYJkrYY/SBk
|
||||
-> ssh-ed25519 2XrTgw +FkRMJR2M2KrnR9n8RMrt1m60h4piX4q6c2PuNaIyko
|
||||
AdpWCLZ/zLdmYyeWAX3/lQJ6h2bMGwF84KJVLoxm4aA
|
||||
-> ssh-ed25519 1MUEqQ mLU9wlidwicRLBbhSa9Adwn1t3PlMwnCVGZveFSWBEM
|
||||
1tiHDboRihGgz+xaylQAdbXQqyCVT0l3xYIbF6to0pE
|
||||
-> ssh-ed25519 dgBsjw 9t+XYjncpp7OPAo915xXHNfgnPsIuqL/RV1JyF/f/hk
|
||||
GhuVPIyAcVy18vHG5LSREzCe/zLkZDXNNNuIwOsZ9Go
|
||||
--- 66KHbxaXGMDinv6CbC2dL5vHNzR9EJdAYdzoUzN5nKI
|
||||
ìŠpH:rØkMµ¨¡mU:GiæÁL#%/©ÀuÌ<75>ÒílzÙ¶/Èí9¨ù|Ô
þûAѬ»2Aü{A 1Vc
|
||||
ʚ€R¯€ájŒŸ‚SéÐ¥Ò
|
||||
-> ssh-ed25519 Jpc21A EvnCvH6ER6Pied87i9okxBLCx38fNP1fX3wMziJ5PXI
|
||||
b7vN/9pxRWuUrug/bkZIZD+2wSplAGLK+ayO+YYDlCs
|
||||
-> ssh-ed25519 BAs8QA I7dMk+pvKe/bNkIr98muyaOKqTdBitIdrRr5bVN3+DA
|
||||
5D5IGeF6rqF+HNSdDZE/gj0DPHISR3Tzj3Fystm++04
|
||||
-> ssh-ed25519 ofQnlg 3XMrmWBHw6+xfYIn8fZ44ryp1dHS7qVTK0cTJZGjXV0
|
||||
PxuU0/w27wW/335mteby+kNTr83K6SrjvNEsxBFHOEI
|
||||
-> ssh-ed25519 COspvA 5yfMt71p+fx9aIT8ubgsHZa9XEJE6trsOOqgC0VxxBY
|
||||
dEIuIERcnw6dFb7IMmdzM5b4ySmdg7qtR50X5gQTd+8
|
||||
-> ssh-ed25519 2XrTgw ZpXWuF2jRWpxlK9HuYZoZyN144cvaNZubVuLBUEq5kc
|
||||
692sos5focQy0TnUfvz+cLktK2a6tyNS8AWbuDgb4/c
|
||||
-> ssh-ed25519 awJeHA ZXx69b4ZvWbwtwnSFjK031mIpK8lDN1nwxq0N+FgREY
|
||||
f7GrJm2N908qtPEYY8T22JGhfWHXbUTAdRuEFHGLOKo
|
||||
-> ssh-ed25519 dgBsjw mD/FfN+J2djG/3hR98oPHznAhTyVz5Z8jnJNlQXzWSo
|
||||
KULWl9PeO3qwbUNQJix/Zr07l9lsBhPZTR6aeOiyx0M
|
||||
--- EUYAk4OeiL39nwZ7YIlLucUMfBghaegrtgqH+sOUEfI
|
||||
-È<>6Q‡äŸ‡7á·™B+Òpûµe³úµ({<ˆ8í‡My|³¿]˜Ãk¾h:žæZŒ§ãde#Äüúû>3„“€K‘<4B>b¨éÀ¬á®øq^uG
|
||||
Loading…
Add table
Reference in a new issue