Verified Commit bfd6f3a1 authored by Katharina Fey's avatar Katharina Fey 🏴
Browse files

Adding random shit

parent a96656e8
This diff is collapsed.
members = [
# ⚙️ forge
# forge
A small toolkit for managing and rebuilding [NixOS] servers.
- base configurations
- configuration diff's for features
- meta configs to assemble diffs
What am I trying to solve?
It provides a simple HTTP server which listens for certain token-hashes
which are sent out by our git backend (gitlab in my case).
If the hash matches, a request is handled.
The actual token is used as a secret for a rebuild key.
- Keep all configuration in a git repo, generate symlinks
- Easy config updates without having to manually operate `git`
- Allow for slight (or not so slight) differences between machines
- examples: `.ssh/config` is _very_ device specific (but can share all the global flags)
- Is this specific and can be solved with `poke` ?
- Account for different versions of software per machine
- Might it just be enough to have a metaconfig which defines what configs are activated?
\ No newline at end of file
This way an attacker would need to know the actual token
to get access to the rebuild-key,
but the hash can be stored as part of the configuration
for request checking, without revealing the token secret
## Setup
There's two ways to use `forge`
* As part of the `forge.nix` module (recommended)
* As a standalone server
The server has the ability to either read it's configuration from
`forge.yml` which can be provided as a path via a CLI flag
or the `FORGE_CONFIG_PATH` env variable.
In case it is run via the `forge.nix` module (oh yea!)
you can configure the server with the following code:
services.forge = {
enable = true; # Enable `forge`
route = "/rebuild"; # The route to handle (on port 443)
token = "<validation token here>";
There are many more options exposed via the `forge.nix` module so do check those out
if you want to have more fine-grained control over your server.
name = "forge-cli"
version = "0.1.0"
authors = ["Katharina Fey <>"]
edition = "2018"
libforge = { path = "../libforge" }
use libforge::clap::{App, AppSettings, Arg, SubCommand};
mod secret;
mod setup;
fn main() {
let app = App::new("forge-cli")
.about("Management CLI for forge")
.about("Create embeddable configuration secrets")
.help("The type of secret")
.possible_values(&["token", "key"]),
.help("Some secret data"),
.about("A guided setup of the forge server (recommended)")
match app.get_matches().subcommand() {
("setup", _) => setup::run(),
("secret", Some(m)) => {
secret::run(m.value_of("TYPE").unwrap(), m.value_of("SECRET").unwrap())
_ => unreachable!(),
//! The `secret` utility module which hashes tokens and encrypts user keys
use libforge;
/// The module version
pub const VERSION: &'static str = "0.1.0";
/// Run the `secret` module
pub fn run(tt: &str, secret: &str) {
/// The module version
pub const VERSION: &'static str = "0.1.0";
pub fn run() {
name = "forge-server"
version = "0.1.0"
authors = ["Katharina Fey <>"]
edition = "2018"
libforge = { path = "../libforge" }
actix-web = "*"
json = "*"
use actix_web::{http, HttpMessage, server, App, HttpRequest, Json, Responder};
use libforge::clap::{App as ClapApp, Arg, ArgMatches};
use std::convert::From;
use std::env;
#[derive(Clone, Debug)]
struct Params {
bind: String,
port: u16,
route: String,
token: String,
impl<'a> From<ArgMatches<'a>> for Params {
fn from(m: ArgMatches<'a>) -> Self {
Self {
bind: m
port: m
route: m
token: m.value_of("TOKEN").unwrap().into(),
fn handle_token(req: &HttpRequest) -> impl Responder {
println!("{:?}", req);
fn main() {
let app = ClapApp::new("forge-server")
.about("The `forge` deployment server")
.help("Address to bind to (default"),
.help("Port to bind to (default 12220)"),
.help("Route to bind to (default \"/rebuild\")"),
.help("Token to accept (required)"),
// Get parameters from CLI, env vars or default values
let params: Params = app.get_matches().into();
let route = params.route.clone();
server::new(move || {
App::new().resource(&params.bind, |r| {
}).bind(&format!("{}:{}", params.bind, params.port))
{ ... }:
options = {};
config = {};
name = "libforge"
version = "0.1.0"
authors = ["Katharina Fey <>"]
edition = "2018"
miscreant = "*"
base64 = "*"
clap = "*"
//! Common forge library
pub use clap;
/// Hash some data
pub fn sha256_hash(data: &str, salt: &str ) -> String {
salt.to_owned() + "::" + data
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment