about summary refs log tree commit diff
path: root/users
diff options
context:
space:
mode:
Diffstat (limited to 'users')
-rw-r--r--users/grfn/xanthous/server/module.nix6
-rw-r--r--users/grfn/xanthous/server/src/main.rs28
2 files changed, 29 insertions, 5 deletions
diff --git a/users/grfn/xanthous/server/module.nix b/users/grfn/xanthous/server/module.nix
index 11adda955d2c..cbc10c014de5 100644
--- a/users/grfn/xanthous/server/module.nix
+++ b/users/grfn/xanthous/server/module.nix
@@ -24,6 +24,11 @@ in {
         default = depot.users.grfn.xanthous.server.docker;
         description = "OCI image file to run";
       };
+
+      ed25519SecretKeyFile = mkOption {
+        type = with types; uniq string;
+        description = "Path to the ed25519 secret key for the server";
+      };
     };
   };
 
@@ -36,6 +41,7 @@ in {
         "${toString cfg.port}:22"
         "${toString cfg.metricsPort}:9000"
       ];
+      environment.SECRET_KEY_FILE = "/etc/secrets/xanthous-server-secret-key";
     };
   };
 }
diff --git a/users/grfn/xanthous/server/src/main.rs b/users/grfn/xanthous/server/src/main.rs
index 4476fe48a68d..9bb31bd9b875 100644
--- a/users/grfn/xanthous/server/src/main.rs
+++ b/users/grfn/xanthous/server/src/main.rs
@@ -1,11 +1,12 @@
 use std::net::SocketAddr;
+use std::path::PathBuf;
 use std::pin::Pin;
 use std::process::Command;
 use std::sync::Arc;
 
 use clap::Parser;
 use color_eyre::eyre::Result;
-use eyre::{bail, eyre};
+use eyre::{bail, Context};
 use futures::future::{ready, Ready};
 use futures::Future;
 use metrics_exporter_prometheus::PrometheusBuilder;
@@ -16,6 +17,9 @@ use thrussh::{
     server::{self, Auth, Session},
     CryptoVec,
 };
+use thrussh_keys::decode_openssh;
+use thrussh_keys::key::KeyPair;
+use tokio::fs::File;
 use tokio::io::{AsyncReadExt, AsyncWriteExt};
 use tokio::net::TcpListener;
 use tokio::select;
@@ -55,17 +59,31 @@ struct Opts {
     #[clap(long, env = "XANTHOUS_BINARY_PATH")]
     xanthous_binary_path: String,
 
+    /// Path to a file containing the ed25519 secret key for the server
+    #[clap(long, env = "SECRET_KEY_FILE")]
+    secret_key_file: PathBuf,
+
     /// Level to log at
     #[clap(long, env = "LOG_LEVEL", default_value = "info")]
     log_level: String,
 }
 
 impl Opts {
-    fn ssh_server_config(&self) -> Result<server::Config> {
+    async fn read_secret_key(&self) -> Result<KeyPair> {
+        let mut file = File::open(&self.secret_key_file)
+            .await
+            .context("Reading secret key file")?;
+        let mut secret_key = Vec::with_capacity(464);
+        file.read_to_end(&mut secret_key).await?;
+        Ok(decode_openssh(&secret_key, None)?)
+    }
+
+    async fn ssh_server_config(&self) -> Result<server::Config> {
+        let key_pair = self.read_secret_key().await?;
+
         Ok(server::Config {
             server_id: "SSH-2.0-xanthous".to_owned(),
-            keys: vec![thrussh_keys::key::KeyPair::generate_ed25519()
-                .ok_or_else(|| eyre!("Could not generate ed25519 key"))?],
+            keys: vec![key_pair],
             ..Default::default()
         })
     }
@@ -301,7 +319,7 @@ async fn main() -> Result<()> {
         .install()?;
     metrics::register();
 
-    let config = Arc::new(opts.ssh_server_config()?);
+    let config = Arc::new(opts.ssh_server_config().await?);
     info!(address = %opts.address, "Listening for new SSH connections");
     let listener = TcpListener::bind(&opts.address).await?;