mirror of
https://github.com/TrustTunnel/TrustTunnel.git
synced 2026-05-02 06:57:06 +00:00
Pull request #73: Introduce a docker image to set up an endpoint
Merge in ADGUARD-CORE-LIBS/vpn-libs-endpoint from feature/AG-22970 to master Squashed commit of the following: commit 98ba1f1c8157786afa476077463dd23598a2cfea Author: Sergei Gunchenko <s.gunchenko@adguard.com> Date: Mon Jul 17 11:08:15 2023 +0300 clean up commit 2917030a1bd15323904693da021dfbff64b7d691 Author: Sergei Gunchenko <s.gunchenko@adguard.com> Date: Mon Jul 17 11:06:06 2023 +0300 changelog commit bad35fd0a99c932e0a2e6ca2d00ae2c61f80eefc Author: Sergei Gunchenko <s.gunchenko@adguard.com> Date: Mon Jul 17 10:53:34 2023 +0300 Introduce a docker image to set up an endpoint and a makefile to ease the setup procedure commit 5c9d1148320dff2ca75c366fc911d478678bcf26 Author: Sergei Gunchenko <s.gunchenko@adguard.com> Date: Mon Jul 17 10:46:50 2023 +0300 wizard: do not ask for input if a parameter is predefined commit 82222837b220ec30d0b5e1d08bff9077333da242 Author: Sergei Gunchenko <s.gunchenko@adguard.com> Date: Mon Jul 17 10:41:16 2023 +0300 bench: minor
This commit is contained in:
@@ -1,5 +1,11 @@
|
||||
# CHANGELOG
|
||||
|
||||
* Added a [docker image](docker/Dockerfile) with a configured and running endpoint.
|
||||
* Added a [Makefile](Makefile) to simplify building and running the endpoint.
|
||||
* Setup Wizard now doesn't ask for parameters specified through command line arguments.
|
||||
E.g., with `setup_wizard --lib-settings vpn.toml` it won't ask a user for the library
|
||||
settings file path.
|
||||
|
||||
## 0.9.47
|
||||
|
||||
* Removed RADIUS-based authenticator
|
||||
|
||||
87
Makefile
Normal file
87
Makefile
Normal file
@@ -0,0 +1,87 @@
|
||||
BUILD_TYPE ?= release
|
||||
ifeq ($(BUILD_TYPE), release)
|
||||
CARGO_BUILD_TYPE = --release
|
||||
endif
|
||||
LOG_LEVEL ?= trace
|
||||
CONFIG_FILE ?= vpn.toml
|
||||
HOSTS_CONFIG_FILE ?= hosts.toml
|
||||
DOCKER_IMAGE_NAME ?= adguard-vpn-endpoint
|
||||
ENDPOINT_URL ?= git@github.com:AdguardTeam/VpnLibsEndpointPrivate.git
|
||||
ENDPOINT_VERSION ?= master
|
||||
ENDPOINT_HOSTNAME ?= vpn.endpoint
|
||||
DOCKER_DIR = docker
|
||||
DOCKER_ENDPOINT_DIR = vpn-libs-endpoint
|
||||
DOCKER_ENDPOINT_CONFIG_DIR = config
|
||||
LISTEN_ADDRESS ?= 0.0.0.0
|
||||
LISTEN_PORT ?= 443
|
||||
|
||||
|
||||
.PHONY: endpoint/build-wizard
|
||||
## Build the setup wizard
|
||||
endpoint/build-wizard:
|
||||
cargo build $(CARGO_BUILD_TYPE) --bin setup_wizard
|
||||
|
||||
.PHONY: endpoint/setup
|
||||
## Run the setup wizard to create all the required configuration files
|
||||
endpoint/setup: endpoint/build-wizard
|
||||
cargo run $(CARGO_BUILD_TYPE) --bin setup_wizard -- \
|
||||
--hostname "$(ENDPOINT_HOSTNAME)" \
|
||||
--address "$(LISTEN_ADDRESS):$(LISTEN_PORT)" \
|
||||
--lib-settings "$(CONFIG_FILE)" \
|
||||
--hosts-settings "$(HOSTS_CONFIG_FILE)"
|
||||
|
||||
.PHONY: endpoint/build
|
||||
## Build the endpoint
|
||||
endpoint/build:
|
||||
cargo build $(CARGO_BUILD_TYPE) --bin vpn_endpoint
|
||||
|
||||
.PHONY: endpoint/run
|
||||
## Run the endpoint with the existing configuration files
|
||||
endpoint/run: endpoint/build
|
||||
cargo run $(CARGO_BUILD_TYPE) --bin vpn_endpoint -- \
|
||||
-l "$(LOG_LEVEL)" "$(CONFIG_FILE)" "$(HOSTS_CONFIG_FILE)"
|
||||
|
||||
.PHONY: endpoint/clean
|
||||
## Clean cargo artifacts
|
||||
endpoint/clean:
|
||||
cargo clean
|
||||
|
||||
.PHONY: docker/-checkout-repo
|
||||
docker/-checkout-repo:
|
||||
@if [ ! -d "$(DOCKER_DIR)/$(DOCKER_ENDPOINT_DIR)" ]; then \
|
||||
git clone "$(ENDPOINT_URL)" "$(DOCKER_DIR)/$(DOCKER_ENDPOINT_DIR)" && \
|
||||
git checkout "$(ENDPOINT_VERSION)"; \
|
||||
fi
|
||||
|
||||
.PHONY: docker/build
|
||||
## Build a docker image with the configured endpoint instance
|
||||
docker/build: docker/-checkout-repo
|
||||
docker build -t "$(DOCKER_IMAGE_NAME)" \
|
||||
--build-arg LOG_LEVEL="$(LOG_LEVEL)" \
|
||||
--build-arg CONFIG_FILE="$(CONFIG_FILE)" \
|
||||
--build-arg HOSTS_CONFIG_FILE="$(HOSTS_CONFIG_FILE)" \
|
||||
--build-arg ENDPOINT_DIR="$(DOCKER_ENDPOINT_DIR)" \
|
||||
./docker
|
||||
|
||||
.PHONY: docker/run
|
||||
## Run the docker image
|
||||
docker/run: docker/build
|
||||
docker run -d \
|
||||
-p $(LISTEN_PORT):$(LISTEN_PORT) \
|
||||
-p $(LISTEN_PORT):$(LISTEN_PORT)/udp \
|
||||
"$(DOCKER_IMAGE_NAME)"
|
||||
|
||||
.PHONY: docker/setup-and-run
|
||||
## Create an endpoint setup, build a docker image containing that setup and run the image.
|
||||
## That is, it is a shorthand for the `endpoint/setup + docker/build + docker/run`.
|
||||
docker/setup-and-run:
|
||||
mkdir -p "$(DOCKER_DIR)/$(DOCKER_ENDPOINT_CONFIG_DIR)"
|
||||
cd "$(DOCKER_DIR)/$(DOCKER_ENDPOINT_CONFIG_DIR)" && make -f ../../Makefile endpoint/setup
|
||||
make docker/run
|
||||
|
||||
.PHONY: docker/clean
|
||||
## Clean docker image
|
||||
docker/clean:
|
||||
docker image rm -f "$(DOCKER_IMAGE_NAME)"
|
||||
rm -rf "$(DOCKER_DIR)/$(DOCKER_ENDPOINT_DIR)"
|
||||
rm -rf "$(DOCKER_DIR)/$(DOCKER_ENDPOINT_CONFIG_DIR)"
|
||||
@@ -7,8 +7,6 @@ ARG CONFIG_FILE="vpn.conf"
|
||||
ARG TLS_HOSTS_SETTINGS_FILE="tls_hosts.conf"
|
||||
ARG LOG_LEVEL="info"
|
||||
|
||||
RUN apt install -y openssl
|
||||
|
||||
COPY $ENDPOINT_DIR/lib/Cargo.toml /tmp/Cargo.toml
|
||||
RUN cargo fetch --manifest-path /tmp/Cargo.toml && rm /tmp/Cargo.toml
|
||||
|
||||
|
||||
36
docker/Dockerfile
Normal file
36
docker/Dockerfile
Normal file
@@ -0,0 +1,36 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM python:3.11-slim-bullseye
|
||||
|
||||
ARG CERTS_DIR="certs"
|
||||
ARG CONFIG_FILE="vpn.toml"
|
||||
ARG CREDENTIALS_FILE="credentials.toml"
|
||||
ARG ENDPOINT_DIR="vpn-libs-endpoint"
|
||||
ARG CONFIG_DIR="config"
|
||||
ARG HOSTS_CONFIG_FILE="hosts.toml"
|
||||
ARG LOG_LEVEL="info"
|
||||
ARG RUST_CHANNEL=1.67
|
||||
|
||||
RUN apt update && \
|
||||
apt install -y build-essential cmake curl make
|
||||
|
||||
# Install Rust and Cargo
|
||||
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain $RUST_CHANNEL
|
||||
ENV PATH="/root/.cargo/bin:$PATH"
|
||||
|
||||
COPY "$ENDPOINT_DIR" "/$ENDPOINT_DIR"
|
||||
WORKDIR "$ENDPOINT_DIR"
|
||||
|
||||
RUN make endpoint/build
|
||||
|
||||
COPY "$CONFIG_DIR" "/$ENDPOINT_DIR/$CONFIG_DIR"
|
||||
WORKDIR "/$ENDPOINT_DIR/$CONFIG_DIR"
|
||||
|
||||
ENV LOG_LEVEL="$LOG_LEVEL" \
|
||||
CONFIG_FILE="$CONFIG_FILE" \
|
||||
HOSTS_CONFIG_FILE="$HOSTS_CONFIG_FILE" \
|
||||
RUST_BACKTRACE=1
|
||||
ENTRYPOINT make -f ../Makefile endpoint/run \
|
||||
LOG_LEVEL="$LOG_LEVEL" \
|
||||
CONFIG_FILE="$CONFIG_FILE" \
|
||||
HOSTS_CONFIG_FILE="$HOSTS_CONFIG_FILE" \
|
||||
>>/tmp/vpn.log 2>&1
|
||||
@@ -13,11 +13,13 @@ pub struct Built {
|
||||
|
||||
pub fn build() -> Built {
|
||||
let builder = Settings::builder()
|
||||
.listen_address(ask_for_input(
|
||||
Settings::doc_listen_address(),
|
||||
Some(crate::get_predefined_params().listen_address.clone()
|
||||
.unwrap_or(Settings::default_listen_address().to_string())),
|
||||
)).unwrap();
|
||||
.listen_address(
|
||||
crate::get_predefined_params().listen_address.clone()
|
||||
.unwrap_or_else(|| ask_for_input(
|
||||
Settings::doc_listen_address(),
|
||||
Some(Settings::default_listen_address().to_string()),
|
||||
))
|
||||
).unwrap();
|
||||
|
||||
Built {
|
||||
settings: builder
|
||||
|
||||
@@ -128,11 +128,11 @@ Required in non-interactive mode."#),
|
||||
let built = library_settings::build();
|
||||
println!("The library settings are successfully built\n");
|
||||
|
||||
let path = ask_for_input::<String>(
|
||||
"Path to a file to store the library settings",
|
||||
Some(get_predefined_params().library_settings_file.clone()
|
||||
.unwrap_or("vpn.toml".into())),
|
||||
);
|
||||
let path = get_predefined_params().library_settings_file.clone()
|
||||
.unwrap_or_else(|| ask_for_input::<String>(
|
||||
"Path to a file to store the library settings",
|
||||
Some("vpn.toml".into()),
|
||||
));
|
||||
if checked_overwrite(&path, "Overwrite the existing library settings file?") {
|
||||
let doc = composer::compose_document(&built.settings, &built.credentials_path);
|
||||
fs::write(&path, doc)
|
||||
@@ -151,11 +151,11 @@ Required in non-interactive mode."#),
|
||||
let settings = tls_hosts_settings::build();
|
||||
println!("The TLS hosts settings are successfully built\n");
|
||||
|
||||
let path = ask_for_input::<String>(
|
||||
"Path to a file to store the TLS hosts settings",
|
||||
Some(get_predefined_params().tls_hosts_settings_file.clone()
|
||||
.unwrap_or("hosts.toml".into())),
|
||||
);
|
||||
let path = get_predefined_params().tls_hosts_settings_file.clone()
|
||||
.unwrap_or_else(|| ask_for_input::<String>(
|
||||
"Path to a file to store the TLS hosts settings",
|
||||
Some("hosts.toml".into()),
|
||||
));
|
||||
if checked_overwrite(&path, "Overwrite the existing TLS hosts settings file?") {
|
||||
fs::write(
|
||||
&path,
|
||||
|
||||
@@ -15,12 +15,14 @@ const DEFAULT_CERTIFICATE_FOLDER: &str = "certs";
|
||||
const DEFAULT_HOSTNAME: &str = "vpn.endpoint";
|
||||
|
||||
pub fn build() -> TlsHostsSettings {
|
||||
let cert = lookup_existent_cert()
|
||||
.and_then(|x| (crate::get_mode() != Mode::NonInteractive
|
||||
&& ask_for_agreement(&format!("Use an existent certificate? {:?}", x)))
|
||||
.then_some(x))
|
||||
.or_else(|| (crate::get_mode() == Mode::NonInteractive
|
||||
|| ask_for_agreement("Generate a self-signed certificate?"))
|
||||
let cert = (crate::get_predefined_params().hostname.is_some()
|
||||
|| crate::get_mode() == Mode::NonInteractive)
|
||||
.then(generate_cert).flatten()
|
||||
.or_else(|| lookup_existent_cert()
|
||||
.and_then(|x| (crate::get_mode() != Mode::NonInteractive
|
||||
&& ask_for_agreement(&format!("Use an existent certificate? {:?}", x)))
|
||||
.then_some(x)))
|
||||
.or_else(|| ask_for_agreement("Generate a self-signed certificate?")
|
||||
.then(generate_cert).flatten())
|
||||
.or_else(|| {
|
||||
let pair = ask_for_input::<String>(
|
||||
@@ -42,10 +44,10 @@ pub fn build() -> TlsHostsSettings {
|
||||
});
|
||||
|
||||
let hostname = cert.as_ref().map(|x| x.common_name.clone())
|
||||
.or_else(|| crate::get_predefined_params().hostname.clone())
|
||||
.unwrap_or_else(|| ask_for_input::<String>(
|
||||
"Endpoint hostname (used for serving TLS connections)",
|
||||
Some(crate::get_predefined_params().hostname.clone()
|
||||
.unwrap_or_else(|| DEFAULT_HOSTNAME.into())),
|
||||
Some(DEFAULT_HOSTNAME.into()),
|
||||
));
|
||||
|
||||
TlsHostsSettings::builder()
|
||||
@@ -134,11 +136,11 @@ fn parse_cert(cert: Either<&str, (&str, &str)>) -> Option<Cert> {
|
||||
fn generate_cert() -> Option<Cert> {
|
||||
let (common_name, alt_names) = {
|
||||
println!("Let's generate a self-signed certificate.");
|
||||
let name = ask_for_input::<String>(
|
||||
"Endpoint hostname (used for serving TLS connections)",
|
||||
Some(crate::get_predefined_params().hostname.clone()
|
||||
.unwrap_or_else(|| DEFAULT_HOSTNAME.into())),
|
||||
);
|
||||
let name = crate::get_predefined_params().hostname.clone()
|
||||
.unwrap_or_else(|| ask_for_input::<String>(
|
||||
"Endpoint hostname (used for serving TLS connections)",
|
||||
Some(DEFAULT_HOSTNAME.into()),
|
||||
));
|
||||
(name.clone(), vec![name.clone(), format!("*.{}", name)])
|
||||
};
|
||||
let mut params = rcgen::CertificateParams::new(alt_names.clone());
|
||||
|
||||
Reference in New Issue
Block a user