Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b90ea0bb11 | ||
|
|
5b949ec034 | ||
|
|
43ee97bc38 | ||
|
|
3ac4d4f9dc | ||
|
|
b111fffeaa | ||
|
|
7ca05baff1 |
@@ -96,6 +96,58 @@ Working browser with a broad feature set:
|
||||
See [`docs/webkit-poc-findings.md`](docs/webkit-poc-findings.md) for the
|
||||
friction report from the POC phase.
|
||||
|
||||
## Install
|
||||
|
||||
One-command install on Debian 13 (trixie) or similar (x86_64, WebKitGTK 4.1):
|
||||
|
||||
```bash
|
||||
curl -fsSL https://git.laantungir.net/laantungir/sovereign_browser/raw/branch/master/install.sh | bash
|
||||
```
|
||||
|
||||
This downloads and runs [`install.sh`](install.sh), which:
|
||||
|
||||
1. Installs runtime dependencies via `apt` (WebKitGTK 4.1, libsoup, curl, etc.)
|
||||
2. Installs **Tor** via `apt` (used for `.onion` routing)
|
||||
3. Builds and installs **FIPS** from source with `CAP_NET_ADMIN` (used for `.fips` mesh routing)
|
||||
4. Downloads the latest prebuilt `sovereign_browser` binary from the [Gitea releases](https://git.laantungir.net/laantungir/sovereign_browser/releases) (falls back to a source build if no binary is available)
|
||||
5. Installs a `sovereign-browser` wrapper command to `/usr/local/bin`
|
||||
|
||||
After install, start the browser with:
|
||||
|
||||
```bash
|
||||
sovereign-browser start --login-method generate
|
||||
```
|
||||
|
||||
### Install options
|
||||
|
||||
```bash
|
||||
# Non-root install to a user-writable prefix
|
||||
curl -fsSL <url> | INSTALL_PREFIX=$HOME/.local bash -s -- --yes
|
||||
|
||||
# Force a source build instead of downloading the prebuilt binary
|
||||
curl -fsSL <url> | bash -s -- --build-from-source
|
||||
|
||||
# Review the script before running it
|
||||
curl -fsSL <url> -o install.sh
|
||||
less install.sh
|
||||
bash install.sh
|
||||
```
|
||||
|
||||
Run `bash install.sh --help` for the full option list.
|
||||
|
||||
### What the install requires
|
||||
|
||||
| Requirement | Why |
|
||||
|---|---|
|
||||
| Debian 13+ / Ubuntu 24.04+ (WebKitGTK 4.1) | The browser is dynamically linked against `libwebkit2gtk-4.1` |
|
||||
| x86_64 | Prebuilt binary is x86-64; arm64 needs `--build-from-source` |
|
||||
| `sudo` / root | For `apt install`, `setcap` on the FIPS binary, and writing to `/usr/local` |
|
||||
| Internet access | To download the binary, apt packages, and the FIPS source |
|
||||
|
||||
Tor and FIPS are **installed by default** (not optional). If either is absent at runtime the browser degrades gracefully — clearnet still works, `.onion`/`.fips` show an error page — but the installer sets them up so everything works out of the box.
|
||||
|
||||
---
|
||||
|
||||
## Build
|
||||
|
||||
Requires Debian 13 (trixie) or similar with WebKitGTK 4.1 dev headers:
|
||||
|
||||
+201
-45
@@ -5,7 +5,8 @@ set -euo pipefail
|
||||
#
|
||||
# Installs:
|
||||
# * apt runtime deps (WebKitGTK 4.1, libsoup-3, tor, build toolchain)
|
||||
# * FIPS (built from source from https://github.com/jmcorgan/fips) with CAP_NET_ADMIN
|
||||
# * FIPS prebuilt binary from GitHub releases (source-build fallback via
|
||||
# --build-fips-from-source) with CAP_NET_ADMIN
|
||||
# * sovereign_browser prebuilt binary from Gitea releases (source-build fallback)
|
||||
# * a `sovereign-browser` wrapper that detaches the GUI
|
||||
#
|
||||
@@ -20,18 +21,22 @@ set -euo pipefail
|
||||
|
||||
GITEA_API="https://git.laantungir.net/api/v1/repos/laantungir/sovereign_browser"
|
||||
GITEA_DOWNLOAD_BASE="https://git.laantungir.net/laantungir/sovereign_browser/releases/download"
|
||||
FIPS_REPO="https://github.com/jmcorgan/fips.git"
|
||||
SB_REPO="https://git.laantungir.net/laantungir/sovereign_browser.git"
|
||||
FIPS_GITHUB_API="https://api.github.com/repos/jmcorgan/fips/releases/latest"
|
||||
FIPS_REPO="https://github.com/jmcorgan/fips.git"
|
||||
INSTALL_PREFIX="${INSTALL_PREFIX:-/usr/local}"
|
||||
BIN_NAME="sovereign_browser"
|
||||
|
||||
# Runtime apt packages (non-dev). git/build-essential/pkg-config are included
|
||||
# because they're needed for the FIPS source build and the source-build fallback.
|
||||
APT_PACKAGES=(
|
||||
libwebkit2gtk-4.1-0 libsoup-3.0-0 libqrencode0 libsqlite3-0
|
||||
libsecp256k1-1 libssl3 libcurl4 zlib1g
|
||||
libwebkit2gtk-4.1-0 libsoup-3.0-0 libqrencode4 libsqlite3-0
|
||||
libsecp256k1-2 libssl3t64 libcurl4t64 zlib1g
|
||||
tor git build-essential pkg-config
|
||||
libcap2-bin
|
||||
)
|
||||
# libclang-dev is only needed when building FIPS from source (bindgen).
|
||||
APT_PACKAGES_FIPS_SOURCE=(libclang-dev)
|
||||
|
||||
# --- Output helpers ------------------------------------------------------
|
||||
|
||||
@@ -75,21 +80,27 @@ Usage: curl -fsSL <url> | bash
|
||||
or: ./install.sh [options]
|
||||
|
||||
Options:
|
||||
--build-from-source Build from source instead of downloading prebuilt binary
|
||||
--prefix <dir> Install prefix (default: /usr/local)
|
||||
--yes Skip confirmation prompts
|
||||
-h, --help Show this help
|
||||
--build-from-source Build sovereign_browser from source instead of
|
||||
downloading the prebuilt binary
|
||||
--build-fips-from-source Build FIPS from source (cargo) instead of
|
||||
downloading the prebuilt binary. Slower; needs
|
||||
libclang-dev (auto-installed).
|
||||
--prefix <dir> Install prefix (default: /usr/local)
|
||||
--yes Skip confirmation prompts
|
||||
-h, --help Show this help
|
||||
EOF
|
||||
}
|
||||
|
||||
# --- Args ----------------------------------------------------------------
|
||||
|
||||
BUILD_FROM_SOURCE=false
|
||||
BUILD_FIPS_FROM_SOURCE=false
|
||||
ASSUME_YES=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--build-from-source) BUILD_FROM_SOURCE=true; shift ;;
|
||||
--build-fips-from-source) BUILD_FIPS_FROM_SOURCE=true; shift ;;
|
||||
--prefix) INSTALL_PREFIX="${2:-}"; shift 2 ;;
|
||||
--yes|-y) ASSUME_YES=true; shift ;;
|
||||
-h|--help) show_usage; exit 0 ;;
|
||||
@@ -163,12 +174,131 @@ install_deps() {
|
||||
}
|
||||
|
||||
# --- FIPS ----------------------------------------------------------------
|
||||
#
|
||||
# FIPS is a Rust project (https://github.com/jmcorgan/fips). It publishes
|
||||
# prebuilt release tarballs on GitHub Releases containing the `fips` binary
|
||||
# plus tools (fipsctl, fipstop) and systemd units. We download the prebuilt
|
||||
# x86_64 Linux tarball by default — much faster than a cargo build.
|
||||
#
|
||||
# With --build-fips-from-source, we instead clone the repo and run
|
||||
# `cargo build --release` (requires Rust 1.94.1+ via rustup, and libclang-dev
|
||||
# for the rustables/bindgen nftables bindings).
|
||||
|
||||
# Download the prebuilt FIPS tarball from GitHub Releases and extract the
|
||||
# `fips` binary. Outputs a stable binary path on stdout (the file is copied
|
||||
# to a caller-managed temp file so it survives after this function returns).
|
||||
# Returns non-zero on failure so the caller can fall back to a source build.
|
||||
download_fips_prebuilt() {
|
||||
print_info "Querying GitHub for latest FIPS release..."
|
||||
local api_json tag asset_url
|
||||
if ! api_json="$(curl -fsSL "$FIPS_GITHUB_API" 2>/dev/null)"; then
|
||||
print_warning "Could not reach FIPS GitHub releases API."
|
||||
return 1
|
||||
fi
|
||||
tag="$(printf '%s' "$api_json" | grep -oE '"tag_name"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed -E 's/.*"tag_name"[[:space:]]*:[[:space:]]*"([^"]*)".*/\1/')"
|
||||
if [[ -z "$tag" ]]; then
|
||||
print_warning "Could not parse tag_name from FIPS GitHub release JSON."
|
||||
return 1
|
||||
fi
|
||||
# Find the linux-x86_64 tarball asset URL.
|
||||
asset_url="$(printf '%s' "$api_json" | grep -oE '"browser_download_url"[[:space:]]*:[[:space:]]*"[^"]*linux-x86_64\.tar\.gz"' | head -1 | sed -E 's/.*"browser_download_url"[[:space:]]*:[[:space:]]*"([^"]*)".*/\1/')"
|
||||
if [[ -z "$asset_url" ]]; then
|
||||
print_warning "No linux-x86_64 tarball found in FIPS release $tag."
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Use a temp dir for download + extraction. We do NOT use a RETURN trap
|
||||
# here because the caller needs to copy the binary out after this
|
||||
# function returns — a RETURN trap would delete the file first. Instead
|
||||
# we copy the binary to a stable temp file and clean up the extraction
|
||||
# dir ourselves before returning.
|
||||
local tmp fips_bin stable
|
||||
tmp="$(mktemp -d -t fips_dl.XXXXXX)"
|
||||
print_info "Downloading FIPS prebuilt binary: $asset_url"
|
||||
if ! curl -fsSL -o "$tmp/fips.tar.gz" "$asset_url"; then
|
||||
rm -rf "$tmp"
|
||||
print_warning "FIPS tarball download failed."
|
||||
return 1
|
||||
fi
|
||||
if ! tar -xzf "$tmp/fips.tar.gz" -C "$tmp" 2>/dev/null; then
|
||||
rm -rf "$tmp"
|
||||
print_warning "FIPS tarball extraction failed."
|
||||
return 1
|
||||
fi
|
||||
# The tarball extracts to fips-<ver>-linux-x86_64/fips
|
||||
fips_bin="$(find "$tmp" -type f -name fips 2>/dev/null | head -1 || true)"
|
||||
if [[ -z "$fips_bin" ]] || ! file "$fips_bin" 2>/dev/null | grep -qi ELF; then
|
||||
rm -rf "$tmp"
|
||||
print_warning "FIPS tarball did not contain an ELF 'fips' binary."
|
||||
return 1
|
||||
fi
|
||||
# Copy to a stable path so the caller can access it after we clean up
|
||||
# the extraction dir. mktemp gives a file the caller can rm later.
|
||||
stable="$(mktemp -t fips_binary.XXXXXX)"
|
||||
cp -f "$fips_bin" "$stable"
|
||||
chmod +x "$stable"
|
||||
rm -rf "$tmp"
|
||||
printf '%s' "$stable"
|
||||
}
|
||||
|
||||
# --- Rust toolchain (only for --build-fips-from-source) ------------------
|
||||
|
||||
FIPS_MIN_RUST_MAJOR=1
|
||||
FIPS_MIN_RUST_MINOR=94
|
||||
|
||||
rust_version_ok() {
|
||||
command -v cargo >/dev/null 2>&1 || return 1
|
||||
local ver
|
||||
ver="$(cargo --version 2>/dev/null | grep -oE 'cargo [0-9]+\.[0-9]+\.' | head -1 | sed 's/cargo //; s/\.$//')" || return 1
|
||||
[[ -z "$ver" ]] && return 1
|
||||
local major minor
|
||||
major="${ver%%.*}"
|
||||
minor="${ver#*.}"
|
||||
[[ "$major" -gt "$FIPS_MIN_RUST_MAJOR" ]] && return 0
|
||||
[[ "$major" -eq "$FIPS_MIN_RUST_MAJOR" && "$minor" -ge "$FIPS_MIN_RUST_MINOR" ]] && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
ensure_rust() {
|
||||
if rust_version_ok; then
|
||||
print_info "Rust toolchain OK ($(cargo --version))."
|
||||
return 0
|
||||
fi
|
||||
|
||||
if command -v cargo >/dev/null 2>&1; then
|
||||
print_warning "Installed cargo ($(cargo --version)) is older than FIPS requires (1.94.1+). Installing a newer toolchain via rustup."
|
||||
else
|
||||
print_info "No cargo found. Installing Rust toolchain via rustup."
|
||||
fi
|
||||
|
||||
local rustup_init
|
||||
rustup_init="$(mktemp -t rustup-init.XXXXXX)"
|
||||
if ! curl -fsSL --proto '=https' --tlsv1.2 -o "$rustup_init" https://sh.rustup.rs; then
|
||||
rm -f "$rustup_init"
|
||||
die "Failed to download rustup installer."
|
||||
fi
|
||||
if ! sh "$rustup_init" -y --profile minimal >/dev/null 2>&1; then
|
||||
rm -f "$rustup_init"
|
||||
die "rustup installation failed."
|
||||
fi
|
||||
rm -f "$rustup_init"
|
||||
# shellcheck disable=SC1091
|
||||
. "$HOME/.cargo/env" 2>/dev/null || true
|
||||
export PATH="$HOME/.cargo/bin:$PATH"
|
||||
|
||||
if ! rust_version_ok; then
|
||||
die "Rust toolchain installed but cargo still reports an insufficient version. FIPS requires 1.94.1+."
|
||||
fi
|
||||
print_success "Rust toolchain installed: $(cargo --version)."
|
||||
}
|
||||
|
||||
# Build FIPS from source via cargo. Outputs the binary path on stdout.
|
||||
build_fips_from_source() {
|
||||
print_info "Building FIPS from source ($FIPS_REPO)..."
|
||||
ensure_rust
|
||||
|
||||
install_fips() {
|
||||
print_info "Building and installing FIPS from $FIPS_REPO (required, not optional)..."
|
||||
local tmp
|
||||
tmp="$(mktemp -d)"
|
||||
# Register cleanup for this temp dir (in addition to the global trap).
|
||||
trap "rm -rf '$tmp' 2>/dev/null || true" RETURN
|
||||
|
||||
if ! git clone --depth 1 "$FIPS_REPO" "$tmp/fips"; then
|
||||
@@ -176,40 +306,52 @@ install_fips() {
|
||||
fi
|
||||
|
||||
local fips_dir="$tmp/fips"
|
||||
local built=false
|
||||
|
||||
if [[ -x "$fips_dir/build.sh" ]]; then
|
||||
print_info "FIPS: running ./build.sh"
|
||||
if ( cd "$fips_dir" && ./build.sh ); then built=true; fi
|
||||
print_info "FIPS: running cargo build --release (this can take several minutes)..."
|
||||
if ! ( cd "$fips_dir" && cargo build --release ); then
|
||||
die "cargo build --release failed for FIPS. FIPS is required."
|
||||
fi
|
||||
|
||||
if ! $built && [[ -f "$fips_dir/Makefile" ]]; then
|
||||
print_info "FIPS: running make"
|
||||
if ( cd "$fips_dir" && make ); then built=true; fi
|
||||
fi
|
||||
|
||||
if ! $built && [[ -f "$fips_dir/CMakeLists.txt" ]]; then
|
||||
print_info "FIPS: running cmake"
|
||||
if ( cd "$fips_dir" && cmake -B build && cmake --build build ); then built=true; fi
|
||||
fi
|
||||
|
||||
if ! $built; then
|
||||
die "Could not build FIPS (no build.sh, Makefile, or CMakeLists.txt succeeded). FIPS is required."
|
||||
fi
|
||||
|
||||
# Locate the built fips binary.
|
||||
local fips_bin=""
|
||||
for cand in "$fips_dir/fips" "$fips_dir/build/fips" "$fips_dir/build/src/fips"; do
|
||||
for cand in \
|
||||
"$fips_dir/target/release/fips" \
|
||||
"$fips_dir/target/x86_64-unknown-linux-gnu/release/fips"; do
|
||||
if [[ -x "$cand" ]] && file "$cand" 2>/dev/null | grep -qi ELF; then
|
||||
fips_bin="$cand"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [[ -z "$fips_bin" ]]; then
|
||||
# Last resort: search for any executable named fips.
|
||||
fips_bin="$(find "$fips_dir" -type f -name fips -executable 2>/dev/null | head -1 || true)"
|
||||
fips_bin="$(find "$fips_dir/target" -type f -name fips -executable 2>/dev/null | head -1 || true)"
|
||||
fi
|
||||
[[ -n "$fips_bin" ]] || die "FIPS build succeeded but no 'fips' binary was found."
|
||||
printf '%s' "$fips_bin"
|
||||
}
|
||||
|
||||
install_fips() {
|
||||
print_info "Installing FIPS (required, not optional)..."
|
||||
|
||||
# If source build was requested, install the extra build-time apt deps.
|
||||
if $BUILD_FIPS_FROM_SOURCE; then
|
||||
print_info "Installing FIPS source-build deps (libclang-dev for bindgen)..."
|
||||
local sudo_cmd=""
|
||||
if [[ $EUID -ne 0 ]]; then sudo_cmd="sudo"; fi
|
||||
$sudo_cmd apt-get install -y "${APT_PACKAGES_FIPS_SOURCE[@]}" >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
local fips_bin=""
|
||||
if $BUILD_FIPS_FROM_SOURCE; then
|
||||
fips_bin="$(build_fips_from_source)"
|
||||
else
|
||||
if ! fips_bin="$(download_fips_prebuilt)"; then
|
||||
print_warning "Prebuilt FIPS unavailable — falling back to source build."
|
||||
# Install source-build deps on the fallback path too.
|
||||
local sudo_cmd=""
|
||||
if [[ $EUID -ne 0 ]]; then sudo_cmd="sudo"; fi
|
||||
$sudo_cmd apt-get install -y "${APT_PACKAGES_FIPS_SOURCE[@]}" >/dev/null 2>&1 || true
|
||||
fips_bin="$(build_fips_from_source)"
|
||||
fi
|
||||
fi
|
||||
[[ -n "$fips_bin" && -x "$fips_bin" ]] || die "FIPS binary not available."
|
||||
|
||||
local prefix_bin="$INSTALL_PREFIX/bin"
|
||||
local SUDO
|
||||
@@ -218,6 +360,10 @@ install_fips() {
|
||||
$SUDO cp -f "$fips_bin" "$prefix_bin/fips"
|
||||
$SUDO chmod +x "$prefix_bin/fips"
|
||||
print_success "FIPS binary installed to $prefix_bin/fips"
|
||||
# Clean up the temp binary (download_fips_prebuilt copies to a stable
|
||||
# mktemp file; build_fips_from_source uses a RETURN-trapped dir so its
|
||||
# output is already gone, but rm -f is safe on either).
|
||||
rm -f "$fips_bin" 2>/dev/null || true
|
||||
|
||||
# setcap for CAP_NET_ADMIN (needed to create a TUN interface in managed mode).
|
||||
local setcap_cmd=""
|
||||
@@ -231,7 +377,6 @@ install_fips() {
|
||||
if $setcap_cmd cap_net_admin+ep "$prefix_bin/fips" 2>/dev/null; then
|
||||
print_success "FIPS granted CAP_NET_ADMIN."
|
||||
else
|
||||
# setcap exists but failed — try with sudo explicitly.
|
||||
if $SUDO setcap cap_net_admin+ep "$prefix_bin/fips" 2>/dev/null; then
|
||||
print_success "FIPS granted CAP_NET_ADMIN."
|
||||
else
|
||||
@@ -413,18 +558,29 @@ main() {
|
||||
local method="prebuilt binary from Gitea"
|
||||
$BUILD_FROM_SOURCE && method="source build from $SB_REPO"
|
||||
|
||||
cat >&2 <<EOF
|
||||
${BLUE}[INFO]${NC} sovereign_browser will be installed:
|
||||
${BLUE}[INFO]${NC} Install prefix : $INSTALL_PREFIX
|
||||
${BLUE}[INFO]${NC} Binary method : $method
|
||||
${BLUE}[INFO]${NC} FIPS : built from source ($FIPS_REPO), CAP_NET_ADMIN set
|
||||
${BLUE}[INFO]${NC} Tor : apt package 'tor'
|
||||
${BLUE}[INFO]${NC} apt deps : ${APT_PACKAGES[*]}
|
||||
EOF
|
||||
local fips_method="prebuilt binary from GitHub releases"
|
||||
$BUILD_FIPS_FROM_SOURCE && fips_method="source build ($FIPS_REPO, cargo)"
|
||||
|
||||
# Use print_info so colors render via `echo -e` (a plain `cat` heredoc
|
||||
# would print the literal \033 escape sequences).
|
||||
print_info "sovereign_browser will be installed:"
|
||||
print_info " Install prefix : $INSTALL_PREFIX"
|
||||
print_info " Binary method : $method"
|
||||
print_info " FIPS : $fips_method, CAP_NET_ADMIN set"
|
||||
print_info " Tor : apt package 'tor'"
|
||||
print_info " apt deps : ${APT_PACKAGES[*]}"
|
||||
|
||||
if ! $ASSUME_YES; then
|
||||
echo -e "${YELLOW}[WARNING]${NC} This will run apt-get install (sudo) and clone/build FIPS. Continue? [y/N] " >&2
|
||||
read -r reply || reply=""
|
||||
print_warning "This will run apt-get install (sudo) and clone/build FIPS. Continue? [y/N]"
|
||||
# Read from /dev/tty, not stdin: in `curl | bash` mode stdin is the
|
||||
# curl pipe (the script text), so a plain `read` would hit EOF and
|
||||
# abort immediately. /dev/tty is the user's terminal.
|
||||
if [[ -r /dev/tty ]]; then
|
||||
read -r reply < /dev/tty || reply=""
|
||||
else
|
||||
# No tty available (e.g. non-interactive CI) — require --yes.
|
||||
die "No tty available for confirmation. Re-run with --yes to skip prompts."
|
||||
fi
|
||||
reply="${reply:-n}"
|
||||
if [[ ! "${reply,,}" =~ ^y(es)?$ ]]; then
|
||||
die "Aborted by user."
|
||||
|
||||
Binary file not shown.
+2
-2
@@ -11,9 +11,9 @@
|
||||
#ifndef SOVEREIGN_BROWSER_VERSION_H
|
||||
#define SOVEREIGN_BROWSER_VERSION_H
|
||||
|
||||
#define SB_VERSION "v0.0.35"
|
||||
#define SB_VERSION "v0.0.41"
|
||||
#define SB_VERSION_MAJOR 0
|
||||
#define SB_VERSION_MINOR 0
|
||||
#define SB_VERSION_PATCH 35
|
||||
#define SB_VERSION_PATCH 41
|
||||
|
||||
#endif /* SOVEREIGN_BROWSER_VERSION_H */
|
||||
|
||||
Reference in New Issue
Block a user