Compare commits

..

11 commits

Author SHA1 Message Date
f410f3bd11 Merge pull request 'flake.nix: switch to crane' (#21) from Armael/tricot:crane into main
Reviewed-on: Deuxfleurs/tricot#21
Reviewed-by: Quentin <quentin@dufour.io>
2025-02-20 13:58:59 +00:00
Armaël Guéneau
888f499b97 flake.nix: switch to crane 2025-02-20 13:34:06 +01:00
3b19439f9a Merge pull request 'README: document that the "tricot" tag supports glob patterns' (#20) from armael-patch-1 into main
Reviewed-on: Deuxfleurs/tricot#20
2025-02-19 06:58:35 +00:00
8c7f974e06 README: document that the "tricot" tag supports glob patterns 2025-02-09 14:49:04 +00:00
2a679f97b6 Merge pull request 'reverse proxy: also add tag-based headers for redirections' (#17) from Armael/tricot:headers_for_redirects into main
Reviewed-on: Deuxfleurs/tricot#17
2024-12-01 15:31:13 +00:00
Armaël Guéneau
e89f3b67bd reverse proxy: also add tag-based headers for redirections 2024-12-01 15:40:25 +01:00
7540b03cf6 Merge pull request 'Build musl static binaries & update dependencies' (#15) from Armael/tricot:musl into main
Reviewed-on: Deuxfleurs/tricot#15
2024-11-09 20:32:27 +00:00
Armaël Guéneau
408c77d5b9 Add a startup message on stdout (for debugging purposes) 2024-11-09 18:36:37 +01:00
Armaël Guéneau
d20f819582 Build musl static binaries & update flake dependencies 2024-11-08 22:14:18 +01:00
9bb505d977 fix woodpecker trigger 2024-03-20 17:31:56 +01:00
dff06115cc Woodpecker CI 2024-03-20 17:29:03 +01:00
10 changed files with 928 additions and 4214 deletions

View file

@ -1,9 +1,10 @@
---
kind: pipeline
name: default
node:
nix-daemon: 1
when:
event:
- push
- pull_request
- tag
- cron
- manual
steps:
- name: check formatting
@ -16,25 +17,9 @@ steps:
- name: build
image: nixpkgs/nix:nixos-22.05
commands:
- nix build --extra-experimental-features nix-command --extra-experimental-features flakes .#debug.x86_64-linux.tricot
- nix build --extra-experimental-features nix-command --extra-experimental-features flakes .#packages.x86_64-linux.debug
- name: test
image: nixpkgs/nix:nixos-22.05
commands:
- nix build --extra-experimental-features nix-command --extra-experimental-features flakes .#test.x86_64-linux.tricot
- ./result-bin/bin/tricot-*
trigger:
event:
- custom
- push
- pull_request
- tag
- cron
---
kind: signature
hmac: 49cde53ec25364cc3b3f041092c8e658fe9252342253757d86814ca12d5cb0f7
...
- nix build --extra-experimental-features nix-command --extra-experimental-features flakes .#packages.x86_64-linux.test

1356
Cargo.lock generated

File diff suppressed because it is too large Load diff

3514
Cargo.nix

File diff suppressed because it is too large Load diff

View file

@ -26,6 +26,7 @@ hyper = { version = "0.14", features = [ "full" ] }
futures-util = "0.3"
tokio-rustls = "0.24"
hyper-rustls = "0.24"
openssl = { version = "*", features = [ "vendored" ] }
http = "0.2"
structopt = "0.3"
glob = "0.3"
@ -38,9 +39,11 @@ opentelemetry = "0.20"
opentelemetry-prometheus = "0.13"
prometheus = "0.13"
df-consul = "0.3.5"
tikv-jemallocator = { version = "0.5", features = ["profiling"] }
tikv-jemalloc-ctl = "0.5"
common-mem-prof = { git = "https://github.com/GreptimeTeam/greptimedb", rev = "fcff66e03904d80aacb91b8edd4e15240161d264" }
dhat = { version = "0.3", optional = true }
[profile.release]
debug = 1
[features]
dhat-heap = [ "dhat" ]

View file

@ -1,6 +1,6 @@
# Tricot
[![Build Status](https://drone.deuxfleurs.fr/api/badges/Deuxfleurs/tricot/status.svg)](https://drone.deuxfleurs.fr/Deuxfleurs/tricot)
[![status-badge](https://woodpecker.deuxfleurs.fr/api/badges/36/status.svg)](https://woodpecker.deuxfleurs.fr/repos/36)
Tricot is a reverse-proxy for exposing your services via TLS that integrates well with Consul and Nomad.
@ -36,7 +36,7 @@ Tricot uses the following environment variables for its configuration (they can
Backends are configured by adding tags of the following form to the services in Consul:
- `tricot myapp.example.com`: indicates that Tricot should get a TLS certificate for domain myapp.example.com and route traffic for this domain to this service
- `tricot myapp.example.com`: indicates that Tricot should get a TLS certificate for domain myapp.example.com and route traffic for this domain to this service. Also supports glob patterns (for instance, `tricot *` redirects requests for all domains).
- `tricot myapp.example.com 10`: same but with a priority of 10. This is lower than the default priority value of 100, so Tricot will only use this rule if no higher-priority services are available.
- `tricot myapp.example.com/path/to_subresource`: same but indicates that only requests whose paths start with `/path/to/subresource` should be routed to this service
- `tricot myapp.example.com/path/to_subresource 10`: combining the previous two examples

104
flake.lock generated
View file

@ -1,70 +1,30 @@
{
"nodes": {
"cargo2nix": {
"inputs": {
"flake-compat": "flake-compat",
"flake-utils": "flake-utils",
"nixpkgs": [
"nixpkgs"
],
"rust-overlay": "rust-overlay"
},
"crane": {
"locked": {
"lastModified": 1666087781,
"narHash": "sha256-trKVdjMZ8mNkGfLcY5LsJJGtdV3xJDZnMVrkFjErlcs=",
"owner": "Alexis211",
"repo": "cargo2nix",
"rev": "a7a61179b66054904ef6a195d8da736eaaa06c36",
"lastModified": 1739638817,
"narHash": "sha256-pPiI27T416xAAUETorkLAgHQMiLT92moOrf0ItHhtPA=",
"owner": "ipetkov",
"repo": "crane",
"rev": "bef2b45cd1273a9e621fb5292de89f4ed59ad812",
"type": "github"
},
"original": {
"owner": "Alexis211",
"repo": "cargo2nix",
"rev": "a7a61179b66054904ef6a195d8da736eaaa06c36",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1650374568,
"narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "b4a34015c698c7793d592d66adbab377907a2be8",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"owner": "ipetkov",
"repo": "crane",
"type": "github"
}
},
"flake-utils": {
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1694529238,
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
@ -75,58 +35,46 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1696234590,
"narHash": "sha256-mgOzQYTvaTT4bFopVOadlndy2RPwLy60rDjIWOGujwo=",
"lastModified": 1736692550,
"narHash": "sha256-7tk8xH+g0sJkKLTJFOxphJxxOjMDFMWv24nXslaU2ro=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "f902cb49892d300ff15cb237e48aa1cad79d68c3",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1665657542,
"narHash": "sha256-mojxNyzbvmp8NtVtxqiHGhRfjCALLfk9i/Uup68Y5q8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a3073c49bc0163fea6a121c276f526837672b555",
"rev": "7c4869c47090dd7f9f1bdfb49a22aea026996815",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a3073c49bc0163fea6a121c276f526837672b555",
"rev": "7c4869c47090dd7f9f1bdfb49a22aea026996815",
"type": "github"
}
},
"root": {
"inputs": {
"cargo2nix": "cargo2nix",
"nixpkgs": "nixpkgs_2"
"crane": "crane",
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"rust-overlay": "rust-overlay"
}
},
"rust-overlay": {
"inputs": {
"flake-utils": "flake-utils_2",
"nixpkgs": "nixpkgs"
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1682389182,
"narHash": "sha256-8t2nmFnH+8V48+IJsf8AK51ebXNlVbOSVYOpiqJKvJE=",
"lastModified": 1738549608,
"narHash": "sha256-GdyT9QEUSx5k/n8kILuNy83vxxdyUfJ8jL5mMpQZWfw=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "74f1a64dd28faeeb85ef081f32cad2989850322c",
"rev": "35c6f8c4352f995ecd53896200769f80a3e8f22d",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "35c6f8c4352f995ecd53896200769f80a3e8f22d",
"type": "github"
}
},

101
flake.nix
View file

@ -1,41 +1,78 @@
{
description = "A very basic flake";
description = "Tricot, a reverse proxy with consul integration";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/a3073c49bc0163fea6a121c276f526837672b555";
inputs.cargo2nix = {
# As of 2022-10-18: two small patches over unstable branch, one for clippy and one to fix feature detection
url = "github:Alexis211/cargo2nix/a7a61179b66054904ef6a195d8da736eaaa06c36";
# Nixpkgs 24.11 as of 2025-01-12
inputs.nixpkgs.url =
"github:NixOS/nixpkgs/7c4869c47090dd7f9f1bdfb49a22aea026996815";
# Rust overlay as of 2023-04-25
inputs.rust-overlay.url =
"github:oxalica/rust-overlay/74f1a64dd28faeeb85ef081f32cad2989850322c";
# Rust overlay as of 2025-02-03
inputs.rust-overlay.url =
"github:oxalica/rust-overlay/35c6f8c4352f995ecd53896200769f80a3e8f22d";
inputs.rust-overlay.inputs.nixpkgs.follows = "nixpkgs";
inputs.nixpkgs.follows = "nixpkgs";
};
inputs.crane.url = "github:ipetkov/crane";
outputs = { self, nixpkgs, cargo2nix }:
let
pkgs = import nixpkgs {
system = "x86_64-linux";
overlays = [ cargo2nix.overlays.default ];
};
packageFun = import ./Cargo.nix;
rustVersion = "1.68.0";
inputs.flake-utils.url = "github:numtide/flake-utils";
compile = args: compileMode:
outputs = { self, nixpkgs, crane, flake-utils, rust-overlay, ... }:
flake-utils.lib.eachSystem [ "x86_64-linux" ] (localSystem:
let
packageSet = pkgs.rustBuilder.makePackageSet ({
inherit packageFun rustVersion;
} // args);
in
packageSet.workspace.tricot {
inherit compileMode;
crossSystem = "x86_64-unknown-linux-musl";
rustVersion = "1.84.0";
pkgs = import nixpkgs {
# we need a full musl toolchain because we're depending on openssl (a
# C library), which we thus need to compile for musl
inherit localSystem;
crossSystem = { config = crossSystem; };
overlays = [ (import rust-overlay) ];
};
in
{
test.x86_64-linux.tricot = compile { release = false; } "test";
debug.x86_64-linux.tricot = compile { release = false; } "build";
packages.x86_64-linux.tricot = compile { release = true; } "build";
packages.x86_64-linux.default = self.packages.x86_64-linux.tricot;
};
craneLib = (crane.mkLib pkgs).overrideToolchain
(p: p.rust-bin.stable.${rustVersion}.default);
commonArgs = {
src = craneLib.cleanCargoSource ./.;
strictDeps = true;
# required for building openssl
nativeBuildInputs = [
pkgs.perl
];
OPENSSL_STATIC = "yes";
CARGO_BUILD_TARGET = crossSystem;
CARGO_BUILD_RUSTFLAGS = "-C target-feature=+crt-static";
doCheck = false;
};
devArgs = (commonArgs // { CARGO_PROFILE = "dev"; });
releaseArgs = (commonArgs // { CARGO_PROFILE = "release"; });
tricot-deps-dev = craneLib.buildDepsOnly devArgs;
in
{
packages = rec {
default = craneLib.buildPackage releaseArgs;
debug = craneLib.buildPackage (devArgs // {
cargoArtifacts = tricot-deps-dev;
});
test = craneLib.cargoTest (devArgs // {
cargoArtifacts = tricot-deps-dev;
doCheck = true;
});
docker = pkgs.dockerTools.buildImage {
name = "tricot";
config = {
contents = [ pkgs.cacert ];
Cmd = [ "${self.packages.x86_64-linux.default}/bin/tricot" ];
};
};
};
}
);
}

View file

@ -371,8 +371,8 @@ async fn do_proxy(
reverse_proxy::call(remote_addr.ip(), &to_addr, req).await?
};
if response.status().is_success() {
// (TODO: maybe we want to add these headers even if it's not a success?)
if response.status().is_success() || response.status().is_redirection() {
// (TODO: maybe we want to add these headers even if it's not a success or redirection?)
for (header, value) in proxy_to.add_headers.iter() {
response.headers_mut().insert(
HeaderName::from_bytes(header.as_bytes())?,

View file

@ -24,12 +24,9 @@ mod tls_util;
pub use df_consul as consul;
use proxy_config::ProxyConfig;
#[cfg(not(target_env = "msvc"))]
use tikv_jemallocator::Jemalloc;
#[cfg(not(target_env = "msvc"))]
#[cfg(feature = "dhat-heap")]
#[global_allocator]
static GLOBAL: Jemalloc = Jemalloc;
static ALLOC: dhat::Alloc = dhat::Alloc;
#[derive(StructOpt, Debug)]
#[structopt(name = "tricot")]
@ -113,7 +110,6 @@ struct Opt {
pub warmup_cert_memory_store: bool,
}
#[tokio::main(flavor = "multi_thread", worker_threads = 10)]
async fn main() {
#[cfg(feature = "dhat-heap")]
@ -136,6 +132,7 @@ async fn main() {
let opt = Opt::from_args();
info!("Starting Tricot");
println!("Starting Tricot");
let (exit_signal, provoke_exit) = watch_ctrl_c();
let exit_on_err = move |err: anyhow::Error| {
@ -214,8 +211,7 @@ async fn main() {
.then(|_| async { info!("HTTPS server exited") }),
);
let dump_task = tokio::spawn(dump_config_on_change(rx_proxy_config, exit_signal.clone()));
let dump_task = tokio::spawn(dump_config_on_change(rx_proxy_config, exit_signal.clone()));
metrics_task.await.expect("Tokio task await failure");
http_task.await.expect("Tokio task await failure");

View file

@ -70,11 +70,6 @@ impl MetricsServer {
debug!("{} {}", req.method(), req.uri());
let response = match (req.method(), req.uri().path()) {
(&Method::GET, "/hprof") => {
let buff = common_mem_prof::dump_profile().await.unwrap();
tokio::fs::write("memdump.hprof", buff).await.unwrap();
Response::builder().status(204).body(Body::from(vec![])).unwrap()
},
(&Method::GET, "/metrics") => {
let mut buffer = vec![];
let encoder = TextEncoder::new();