Static builds that can install themselves

This commit is contained in:
Dennis Schwerdel 2021-02-14 13:27:26 +01:00
parent c4ff0ed198
commit 4950753548
9 changed files with 130 additions and 21 deletions

View File

@ -3,12 +3,27 @@ linker = "arm-linux-gnueabihf-gcc"
objcopy = { path = "arm-linux-gnueabihf-objcopy" } objcopy = { path = "arm-linux-gnueabihf-objcopy" }
strip = { path = "arm-linux-gnueabihf-strip" } strip = { path = "arm-linux-gnueabihf-strip" }
[target.armv7-unknown-linux-musleabihf]
linker = "arm-linux-gnueabihf-gcc"
objcopy = { path = "arm-linux-gnueabihf-objcopy" }
strip = { path = "arm-linux-gnueabihf-strip" }
[target.arm-unknown-linux-gnueabihf] [target.arm-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc" linker = "arm-linux-gnueabihf-gcc"
objcopy = { path = "arm-linux-gnueabihf-objcopy" } objcopy = { path = "arm-linux-gnueabihf-objcopy" }
strip = { path = "arm-linux-gnueabihf-strip" } strip = { path = "arm-linux-gnueabihf-strip" }
[target.arm-unknown-linux-musleabihf]
linker = "arm-linux-gnueabihf-gcc"
objcopy = { path = "arm-linux-gnueabihf-objcopy" }
strip = { path = "arm-linux-gnueabihf-strip" }
[target.aarch64-unknown-linux-gnu] [target.aarch64-unknown-linux-gnu]
linker = "aarch64-linux-gnu-gcc" linker = "aarch64-linux-gnu-gcc"
objcopy = { path = "aarch64-linux-gnu-objcopy" } objcopy = { path = "aarch64-linux-gnu-objcopy" }
strip = { path = "aarch64-linux-gnu-strip" } strip = { path = "aarch64-linux-gnu-strip" }
[target.aarch64-unknown-linux-musl]
linker = "aarch64-linux-gnu-gcc"
objcopy = { path = "aarch64-linux-gnu-objcopy" }
strip = { path = "aarch64-linux-gnu-strip" }

View File

@ -11,7 +11,7 @@ jobs:
- name: Run builder - name: Run builder
uses: ./.github/actions/build-deb uses: ./.github/actions/build-deb
with: with:
rust: '1.49.0' rust: '1.50.0'
- name: Archive artifacts - name: Archive artifacts
uses: actions/upload-artifact@v1 uses: actions/upload-artifact@v1
with: with:
@ -31,7 +31,7 @@ jobs:
- name: Run builder - name: Run builder
uses: ./.github/actions/build-rpm uses: ./.github/actions/build-rpm
with: with:
rust: '1.49.0' rust: '1.50.0'
- name: Archive artifacts - name: Archive artifacts
uses: actions/upload-artifact@v1 uses: actions/upload-artifact@v1
with: with:

View File

@ -43,6 +43,7 @@ default = ["nat", "websocket", "wizard"]
nat = ["igd"] nat = ["igd"]
websocket = ["tungstenite", "url"] websocket = ["tungstenite", "url"]
wizard = ["dialoguer"] wizard = ["dialoguer"]
installer = []
[[bench]] [[bench]]
name = "criterion" name = "criterion"

View File

@ -11,6 +11,7 @@ RUN apt-get update \
libc6-dev-i386 \ libc6-dev-i386 \
gcc-5-multilib \ gcc-5-multilib \
asciidoctor \ asciidoctor \
musl musl-dev musl-tools \
&& rm -rf /var/cache/dpkg && rm -rf /var/cache/dpkg
RUN ln -s asm-generic/ /usr/include/asm RUN ln -s asm-generic/ /usr/include/asm
@ -19,7 +20,7 @@ RUN useradd -ms /bin/bash user
USER user USER user
WORKDIR /home/user WORKDIR /home/user
ENV RUST=1.49.0 ENV RUST=1.50.0
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain ${RUST} RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain ${RUST}
@ -27,12 +28,18 @@ ENV PATH=/home/user/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
RUN rustup target add i686-unknown-linux-gnu \ RUN rustup target add i686-unknown-linux-gnu \
&& rustup target add armv7-unknown-linux-gnueabihf \ && rustup target add armv7-unknown-linux-gnueabihf \
&& rustup target add aarch64-unknown-linux-gnu && rustup target add aarch64-unknown-linux-gnu \
&& rustup target add x86_64-unknown-linux-musl \
&& rustup target add i686-unknown-linux-musl \
&& rustup target add armv7-unknown-linux-musleabihf \
&& rustup target add aarch64-unknown-linux-musl
RUN cargo install cargo-deb \ RUN cargo install cargo-deb \
&& rm -rf /home/user/.cargo/{git,tmp,registry} && rm -rf /home/user/.cargo/{git,tmp,registry}
ENV UPX_VER=3.96
RUN curl https://github.com/upx/upx/releases/download/v${UPX_VER}/upx-${UPX_VER}-amd64_linux.tar.xz -Lf | tar -xJ --strip-components=1 -C /home/user/.cargo/bin
VOLUME /home/user/.cargo/tmp VOLUME /home/user/.cargo/tmp
VOLUME /home/user/.cargo/git VOLUME /home/user/.cargo/git
VOLUME /home/user/.cargo/registry VOLUME /home/user/.cargo/registry

View File

@ -7,7 +7,7 @@ RUN useradd -ms /bin/bash user
USER user USER user
WORKDIR /home/user WORKDIR /home/user
ENV RUST=1.49.0 ENV RUST=1.50.0
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain ${RUST} RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain ${RUST}

View File

@ -32,24 +32,44 @@ mkdir -p ../dist
docker build --rm -f=Dockerfile-deb -t vpncloud-builder-deb . docker build --rm -f=Dockerfile-deb -t vpncloud-builder-deb .
# x86_64 deb # x86_64 deb
docker_cmd deb 'cd code && cargo deb' if ! [ -f ../dist/vpncloud_${DEB_VERSION}_amd64.deb ]; then
cp $CACHE/deb/target/debian/vpncloud_${DEB_VERSION}_amd64.deb ../dist/vpncloud_${DEB_VERSION}_amd64.deb docker_cmd deb 'cd code && cargo deb'
cp $CACHE/deb/target/debian/vpncloud_${DEB_VERSION}_amd64.deb ../dist/vpncloud_${DEB_VERSION}_amd64.deb
fi
# i386 deb build_deb() {
docker_cmd deb 'cd code && cargo deb --target i686-unknown-linux-gnu' ARCH=$1
cp $CACHE/deb/target/i686-unknown-linux-gnu/debian/vpncloud_${DEB_VERSION}_i386.deb ../dist/vpncloud_${DEB_VERSION}_i386.deb TARGET=$2
if ! [ -f ../dist/vpncloud_${DEB_VERSION}_${ARCH}.deb ]; then
docker_cmd deb "cd code && cargo deb --target ${TARGET}"
cp $CACHE/deb/target/${TARGET}/debian/vpncloud_${DEB_VERSION}_${ARCH}.deb ../dist/vpncloud_${DEB_VERSION}_${ARCH}.deb
fi
}
# arm7hf deb build_deb i386 i686-unknown-linux-gnu
docker_cmd deb 'cd code && cargo deb --target armv7-unknown-linux-gnueabihf' build_deb armhf armv7-unknown-linux-gnueabihf
cp $CACHE/deb/target/armv7-unknown-linux-gnueabihf/debian/vpncloud_${DEB_VERSION}_armhf.deb ../dist/vpncloud_${DEB_VERSION}_armhf.deb build_deb arm64 aarch64-unknown-linux-gnu
# aarch64 deb
docker_cmd deb 'cd code && cargo deb --target aarch64-unknown-linux-gnu' build_static() {
cp $CACHE/deb/target/aarch64-unknown-linux-gnu/debian/vpncloud_${DEB_VERSION}_arm64.deb ../dist/vpncloud_${DEB_VERSION}_arm64.deb ARCH=$1
TARGET=$2
if ! [ -f ../dist/vpncloud_${VERSION}_static_${ARCH} ]; then
docker_cmd deb "cd code && cargo build --release --features installer --target ${TARGET} && upx --lzma target/${TARGET}/release/vpncloud"
cp $CACHE/deb/target/${TARGET}/release/vpncloud ../dist/vpncloud_${VERSION}_static_${ARCH}
fi
}
build_static amd64 x86_64-unknown-linux-musl
build_static i386 i686-unknown-linux-gnu
build_static armhf armv7-unknown-linux-musleabihf
#build_static arm64 aarch64-unknown-linux-musl # fails for unknown reason
docker build --rm -f=Dockerfile-rpm -t vpncloud-builder-rpm . docker build --rm -f=Dockerfile-rpm -t vpncloud-builder-rpm .
# x86_64 rpm if ! [ -f ../dist/vpncloud_${RPM_VERSION}.x86_64.rpm ]; then
docker_cmd rpm 'cd code && cargo rpm build' # x86_64 rpm
cp $CACHE/rpm/target/release/rpmbuild/RPMS/x86_64/vpncloud-${RPM_VERSION}.x86_64.rpm ../dist/vpncloud_${RPM_VERSION}.x86_64.rpm docker_cmd rpm 'cd code && cargo rpm build'
cp $CACHE/rpm/target/release/rpmbuild/RPMS/x86_64/vpncloud-${RPM_VERSION}.x86_64.rpm ../dist/vpncloud_${RPM_VERSION}.x86_64.rpm
fi

View File

@ -573,6 +573,14 @@ pub enum Command {
/// Name of the network /// Name of the network
#[structopt(short, long)] #[structopt(short, long)]
name: Option<String> name: Option<String>
},
/// Install required utility files
#[cfg(feature = "installer")]
Install {
/// Remove installed files again
#[structopt(long)]
uninstall: bool
} }
} }

49
src/installer.rs Normal file
View File

@ -0,0 +1,49 @@
use crate::error::Error;
use std::{
env,
fs::{self, File},
io::Write,
os::unix::fs::PermissionsExt
};
const MANPAGE: &[u8] = include_bytes!("../target/vpncloud.1.gz");
const SERVICE_FILE: &[u8] = include_bytes!("../assets/vpncloud@.service");
const WS_PROXY_SERVICE_FILE: &[u8] = include_bytes!("../assets/vpncloud-wsproxy.service");
const EXAMPLE_CONFIG: &[u8] = include_bytes!("../assets/example.net.disabled");
pub fn install() -> Result<(), Error> {
env::current_exe()
.and_then(|p| fs::copy(p, "/usr/bin/vpncloud"))
.map_err(|e| Error::FileIo("Failed to copy binary", e))?;
fs::set_permissions("/usr/bin/vpncloud", fs::Permissions::from_mode(755))
.map_err(|e| Error::FileIo("Failed to set permissions for binary", e))?;
fs::create_dir_all("/etc/vpncloud").map_err(|e| Error::FileIo("Failed to create config folder", e))?;
fs::set_permissions("/etc/vpncloud", fs::Permissions::from_mode(600))
.map_err(|e| Error::FileIo("Failed to set permissions for config folder", e))?;
File::create("/etc/vpncloud/example.net.disabled")
.and_then(|mut f| f.write_all(EXAMPLE_CONFIG))
.map_err(|e| Error::FileIo("Failed to create example config", e))?;
File::create("/usr/share/man/man1/vpncloud.1.gz")
.and_then(|mut f| f.write_all(MANPAGE))
.map_err(|e| Error::FileIo("Failed to create manpage", e))?;
File::create("/lib/systemd/system/vpncloud@.service")
.and_then(|mut f| f.write_all(SERVICE_FILE))
.map_err(|e| Error::FileIo("Failed to create service file", e))?;
File::create("/lib/systemd/system/vpncloud-wsproxy.service")
.and_then(|mut f| f.write_all(WS_PROXY_SERVICE_FILE))
.map_err(|e| Error::FileIo("Failed to create wsporxy service file", e))?;
info!("Install successful");
Ok(())
}
pub fn uninstall() -> Result<(), Error> {
fs::remove_file("/etc/vpncloud/example.net.disabled").map_err(|e| Error::FileIo("Failed to remove binary", e))?;
fs::remove_file("/usr/share/man/man1/vpncloud.1.gz").map_err(|e| Error::FileIo("Failed to remove manpage", e))?;
fs::remove_file("/lib/systemd/system/vpncloud@.service")
.map_err(|e| Error::FileIo("Failed to remove service file", e))?;
fs::remove_file("/lib/systemd/system/vpncloud-wsproxy.service")
.map_err(|e| Error::FileIo("Failed to remove wsproxy service file", e))?;
fs::remove_file("/usr/bin/vpncloud").map_err(|e| Error::FileIo("Failed to remove binary", e))?;
info!("Uninstall successful");
Ok(())
}

View File

@ -29,6 +29,7 @@ pub mod traffic;
pub mod types; pub mod types;
#[cfg(feature = "wizard")] pub mod wizard; #[cfg(feature = "wizard")] pub mod wizard;
#[cfg(feature = "websocket")] pub mod wsproxy; #[cfg(feature = "websocket")] pub mod wsproxy;
#[cfg(feature = "installer")] pub mod installer;
use structopt::StructOpt; use structopt::StructOpt;
@ -282,6 +283,14 @@ fn main() {
Command::Config { name } => { Command::Config { name } => {
try_fail!(wizard::configure(name), "Wizard failed: {}"); try_fail!(wizard::configure(name), "Wizard failed: {}");
} }
#[cfg(feature = "installer")]
Command::Install { uninstall } => {
if uninstall {
try_fail!(installer::uninstall(), "Uninstall failed: {}");
} else {
try_fail!(installer::install(), "Install failed: {}");
}
}
} }
return return
} }