#!/bin/bash set -euo pipefail opdir="${1?Output dir missing}" : "${HOME?HOME is not set}" check_file_exists() { if [[ -f "$1" ]]; then return 0 fi echo "Warning: File does not exist- $1" return 1 } script_path="$0" script_dir=$(dirname "$(realpath "$0")") common_ssh_cfg_path="${DIYVPN_SSH_CFG:-$script_dir/common_sshconfig}" diyvpn_cfg="${DIYVPN_CFG:-$HOME/.config/diyvpn/servers}" check_file_exists "$common_ssh_cfg_path" generate() { local cfgpath name server_ssh_cfg idle_timeout listen_address cfgpath="$1" name=$(basename "$cfgpath" | tr -d '[:space:]') server_ssh_cfg="$cfgpath"/ssh_config server_config_rc="$cfgpath"/config.rc check_file_exists "$server_ssh_cfg" || return 0 check_file_exists "$server_config_rc" || return 0 # shellcheck disable=SC1090 source "$server_config_rc" idle_timeout="${IDLE_TIMEOUT:-10min}" listen_address="${LISTEN_ADDRESS:?LISTEN_ADDRESS should be set}" header="# Automatically generated by $script_path" cat >"$opdir/diyvpnssh-$name.service" <<-EOF $header [Unit] Description=ssh to $name SourcePath=$server_config_rc StopWhenUnneeded=yes [Service] Type=notify NotifyAccess=all RuntimeDirectory=diyvpn-$name Environment=SSH_CFG_PATH=$server_ssh_cfg ExecStart=ssh -F "$common_ssh_cfg_path" default EOF cat >"$opdir/diyvpnact-$name.service" <<-EOF $header [Unit] Description=Socket activator for diyvpn to server $name SourcePath=$server_config_rc Requires=diyvpnssh-$name.service After=diyvpnssh-$name.service BindsTo=diyvpnssh-$name.service [Service] ExecStart=/usr/lib/systemd/systemd-socket-proxyd --exit-idle-time=$idle_timeout %t/diyvpn-$name/sock EOF cat >"$opdir/diyvpnact-$name.socket" <<-EOF $header [Unit] Description=Socket for diyvpn to server $name SourcePath=$server_config_rc [Socket] ListenStream=$listen_address [Install] WantedBy=sockets.target EOF mkdir -p "$opdir/sockets.target.wants" ln -snf "../diyvpnact-$name.socket" "$opdir/sockets.target.wants" } for server in "$diyvpn_cfg"/*; do if [[ -d "$server" ]]; then (generate "$server") else echo "Ignoring $server. Not a directory." fi done