portable server with embedded for musl has different feature
This commit is contained in:
3
Cargo.lock
generated
3
Cargo.lock
generated
@@ -6888,6 +6888,7 @@ dependencies = [
|
|||||||
"datafusion-table-providers",
|
"datafusion-table-providers",
|
||||||
"dotenvy",
|
"dotenvy",
|
||||||
"email_address",
|
"email_address",
|
||||||
|
"flate2",
|
||||||
"futures",
|
"futures",
|
||||||
"gtin-validate",
|
"gtin-validate",
|
||||||
"iban_validate",
|
"iban_validate",
|
||||||
@@ -6919,6 +6920,8 @@ dependencies = [
|
|||||||
"steel-decimal",
|
"steel-decimal",
|
||||||
"steel-derive",
|
"steel-derive",
|
||||||
"tantivy",
|
"tantivy",
|
||||||
|
"tar",
|
||||||
|
"tempfile",
|
||||||
"thiserror 2.0.18",
|
"thiserror 2.0.18",
|
||||||
"time",
|
"time",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
|||||||
25
flake.nix
25
flake.nix
@@ -10,18 +10,19 @@
|
|||||||
flake-utils.lib.eachDefaultSystem (system:
|
flake-utils.lib.eachDefaultSystem (system:
|
||||||
let
|
let
|
||||||
pkgs = nixpkgs.legacyPackages.${system};
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
|
portableServer = import ./packaging/musl {
|
||||||
|
inherit pkgs;
|
||||||
|
source = self;
|
||||||
|
version = "0.8.41";
|
||||||
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
packages = pkgs.lib.optionalAttrs (system == "x86_64-linux") {
|
||||||
|
portable-server = portableServer;
|
||||||
|
};
|
||||||
|
|
||||||
devShells.default = pkgs.mkShell {
|
devShells.default = pkgs.mkShell {
|
||||||
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath [
|
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath [ pkgs.openssl ];
|
||||||
pkgs.openssl
|
|
||||||
pkgs.krb5
|
|
||||||
pkgs.lz4
|
|
||||||
pkgs.zstd
|
|
||||||
pkgs.libxml2_13.out
|
|
||||||
pkgs.zlib
|
|
||||||
pkgs.readline
|
|
||||||
];
|
|
||||||
|
|
||||||
buildInputs = with pkgs; [
|
buildInputs = with pkgs; [
|
||||||
mermaid-cli
|
mermaid-cli
|
||||||
@@ -51,12 +52,6 @@
|
|||||||
# OpenSSL for crypto dependencies
|
# OpenSSL for crypto dependencies
|
||||||
openssl
|
openssl
|
||||||
openssl.dev
|
openssl.dev
|
||||||
krb5
|
|
||||||
lz4
|
|
||||||
zstd
|
|
||||||
libxml2_13.out
|
|
||||||
zlib
|
|
||||||
readline
|
|
||||||
|
|
||||||
# PostgreSQL for sqlx
|
# PostgreSQL for sqlx
|
||||||
postgresql
|
postgresql
|
||||||
|
|||||||
35
packaging/musl/README.md
Normal file
35
packaging/musl/README.md
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# Portable Linux server build
|
||||||
|
|
||||||
|
This build produces one `x86_64` Linux server executable with embedded
|
||||||
|
PostgreSQL. The Rust program is statically linked against musl. PostgreSQL is
|
||||||
|
compiled against musl without optional host-library dependencies and is stored
|
||||||
|
inside the executable by `postgresql_embedded`.
|
||||||
|
|
||||||
|
PostgreSQL itself remains dynamically loadable so the `btree_gist` extension
|
||||||
|
used by the migrations works. Its musl loader is included in the embedded
|
||||||
|
archive, and static launcher executables invoke every PostgreSQL tool through
|
||||||
|
that loader. Neither glibc, musl, PostgreSQL nor timezone data needs to be
|
||||||
|
installed on the target machine.
|
||||||
|
|
||||||
|
Build directly through the repository's Nix flake:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
nix build '.?submodules=1#portable-server'
|
||||||
|
```
|
||||||
|
|
||||||
|
The `submodules=1` flag includes the workspace's nested Rust repositories. The
|
||||||
|
artifact is available as `result/bin/server`. The derivation initializes a
|
||||||
|
temporary cluster, creates `btree_gist`, sets the timezone to `UTC`, and checks
|
||||||
|
that the final Rust executable has no ELF interpreter.
|
||||||
|
|
||||||
|
The resulting executable is intended for 64-bit Linux kernels. Run it normally:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./result/bin/server server
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the external PostgreSQL build on NixOS when preferred:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cargo build --release --package server --no-default-features
|
||||||
|
```
|
||||||
171
packaging/musl/default.nix
Normal file
171
packaging/musl/default.nix
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
{ pkgs, source, version }:
|
||||||
|
|
||||||
|
let
|
||||||
|
muslPkgs = pkgs.pkgsMusl;
|
||||||
|
postgresqlVersion = "17.10";
|
||||||
|
postgresqlArchiveVersion = "17.10.0";
|
||||||
|
archiveName = "postgresql-${postgresqlArchiveVersion}-x86_64-unknown-linux-musl.tar.gz";
|
||||||
|
|
||||||
|
bootstrapInput = pname: inputs:
|
||||||
|
pkgs.lib.findFirst
|
||||||
|
(input: (input.pname or "") == pname)
|
||||||
|
(throw "Nixpkgs does not expose ${pname} for the musl toolchain")
|
||||||
|
inputs;
|
||||||
|
bootstrapRustPlatform = muslPkgs.makeRustPlatform {
|
||||||
|
rustc = bootstrapInput
|
||||||
|
"rustc-bootstrap"
|
||||||
|
muslPkgs.rustc-unwrapped.nativeBuildInputs;
|
||||||
|
cargo = bootstrapInput
|
||||||
|
"cargo-bootstrap"
|
||||||
|
muslPkgs.cargo.nativeBuildInputs;
|
||||||
|
};
|
||||||
|
|
||||||
|
staticOpenSSL = muslPkgs.openssl.overrideAttrs (old: {
|
||||||
|
configureFlags =
|
||||||
|
builtins.filter (flag: flag != "shared") old.configureFlags
|
||||||
|
++ [ "no-shared" ];
|
||||||
|
doCheck = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
postgresqlSource = pkgs.fetchurl {
|
||||||
|
url = "https://ftp.postgresql.org/pub/source/v${postgresqlVersion}/postgresql-${postgresqlVersion}.tar.bz2";
|
||||||
|
hash = "sha256-B4oDUW3NvbcF/sr0Feo9E6lWxYnkbwn+1ooG+wBZjJA=";
|
||||||
|
};
|
||||||
|
|
||||||
|
postgresqlArchive = muslPkgs.stdenv.mkDerivation {
|
||||||
|
pname = "komp-ac-postgresql-musl";
|
||||||
|
version = postgresqlArchiveVersion;
|
||||||
|
src = postgresqlSource;
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
pkgs.bison
|
||||||
|
pkgs.file
|
||||||
|
pkgs.flex
|
||||||
|
pkgs.gnutar
|
||||||
|
pkgs.gzip
|
||||||
|
pkgs.perl
|
||||||
|
];
|
||||||
|
|
||||||
|
configurePhase = ''
|
||||||
|
runHook preConfigure
|
||||||
|
./configure \
|
||||||
|
--prefix="$out/postgresql" \
|
||||||
|
--disable-nls \
|
||||||
|
--without-gssapi \
|
||||||
|
--without-icu \
|
||||||
|
--without-ldap \
|
||||||
|
--without-libxml \
|
||||||
|
--without-libxslt \
|
||||||
|
--without-llvm \
|
||||||
|
--without-lz4 \
|
||||||
|
--without-openssl \
|
||||||
|
--without-pam \
|
||||||
|
--without-readline \
|
||||||
|
--without-systemd \
|
||||||
|
--without-zlib \
|
||||||
|
--without-zstd
|
||||||
|
runHook postConfigure
|
||||||
|
'';
|
||||||
|
|
||||||
|
buildPhase = ''
|
||||||
|
runHook preBuild
|
||||||
|
make -j"$NIX_BUILD_CORES"
|
||||||
|
make -C contrib/btree_gist -j"$NIX_BUILD_CORES"
|
||||||
|
runHook postBuild
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
make install-strip
|
||||||
|
make -C contrib/btree_gist install
|
||||||
|
|
||||||
|
"$CC" -static -Os -s -Wall -Wextra -Werror \
|
||||||
|
-o postgresql-launcher \
|
||||||
|
${./postgresql-launcher.c}
|
||||||
|
|
||||||
|
mkdir -p "$out/postgresql/libexec"
|
||||||
|
for tool in "$out"/postgresql/bin/*; do
|
||||||
|
toolName="''${tool##*/}"
|
||||||
|
mv "$tool" "$out/postgresql/libexec/$toolName"
|
||||||
|
cp postgresql-launcher "$out/postgresql/bin/$toolName"
|
||||||
|
done
|
||||||
|
cp ${muslPkgs.musl}/lib/ld-musl-x86_64.so.1 \
|
||||||
|
"$out/postgresql/lib/ld-musl-x86_64.so.1"
|
||||||
|
|
||||||
|
file "$out/postgresql/bin/postgres" | grep -q 'statically linked'
|
||||||
|
"$out/postgresql/bin/postgres" --version
|
||||||
|
|
||||||
|
mkdir postgresql-data postgresql-socket
|
||||||
|
"$out/postgresql/bin/initdb" \
|
||||||
|
--auth=trust \
|
||||||
|
--no-locale \
|
||||||
|
-D "$PWD/postgresql-data"
|
||||||
|
"$out/postgresql/bin/pg_ctl" \
|
||||||
|
-D "$PWD/postgresql-data" \
|
||||||
|
-l "$PWD/postgresql.log" \
|
||||||
|
-o "-k $PWD/postgresql-socket -p 55432" \
|
||||||
|
-w start
|
||||||
|
"$out/postgresql/bin/psql" \
|
||||||
|
-h "$PWD/postgresql-socket" \
|
||||||
|
-p 55432 \
|
||||||
|
-d postgres \
|
||||||
|
-c "CREATE EXTENSION btree_gist; SET TIME ZONE 'UTC';"
|
||||||
|
"$out/postgresql/bin/pg_ctl" \
|
||||||
|
-D "$PWD/postgresql-data" \
|
||||||
|
-m fast \
|
||||||
|
-w stop
|
||||||
|
|
||||||
|
tar -C "$out" -czf "$out/${archiveName}" postgresql
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
|
||||||
|
dontPatchELF = true;
|
||||||
|
dontStrip = true;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
bootstrapRustPlatform.buildRustPackage {
|
||||||
|
pname = "komp-ac-server-portable";
|
||||||
|
inherit version source;
|
||||||
|
src = source;
|
||||||
|
|
||||||
|
cargoLock.lockFile = ../../Cargo.lock;
|
||||||
|
cargoBuildFlags = [
|
||||||
|
"--package"
|
||||||
|
"server"
|
||||||
|
"--no-default-features"
|
||||||
|
"--features"
|
||||||
|
"portable-postgres"
|
||||||
|
];
|
||||||
|
auditable = false;
|
||||||
|
doCheck = false;
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
pkgs.binutils
|
||||||
|
pkgs.cmake
|
||||||
|
pkgs.file
|
||||||
|
pkgs.pkg-config
|
||||||
|
pkgs.protobuf
|
||||||
|
];
|
||||||
|
buildInputs = [ staticOpenSSL ];
|
||||||
|
|
||||||
|
OPENSSL_STATIC = "1";
|
||||||
|
OPENSSL_LIB_DIR = "${staticOpenSSL.out}/lib";
|
||||||
|
OPENSSL_INCLUDE_DIR = "${staticOpenSSL.dev}/include";
|
||||||
|
POSTGRESQL_VERSION = "=${postgresqlArchiveVersion}";
|
||||||
|
KOMP_AC_POSTGRESQL_ARCHIVE = "${postgresqlArchive}/${archiveName}";
|
||||||
|
KOMP_AC_POSTGRESQL_VERSION = postgresqlArchiveVersion;
|
||||||
|
SQLX_OFFLINE = "true";
|
||||||
|
RUSTFLAGS = "-Ctarget-feature=+crt-static";
|
||||||
|
|
||||||
|
postInstall = ''
|
||||||
|
file "$out/bin/server" | grep -q 'statically linked'
|
||||||
|
! readelf -l "$out/bin/server" | grep -q 'Requesting program interpreter'
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
description = "Portable komp_ac server with embedded musl PostgreSQL";
|
||||||
|
license = pkgs.lib.licenses.agpl3Plus;
|
||||||
|
platforms = [ "x86_64-linux" ];
|
||||||
|
mainProgram = "server";
|
||||||
|
};
|
||||||
|
}
|
||||||
92
packaging/musl/postgresql-launcher.c
Normal file
92
packaging/musl/postgresql-launcher.c
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static void fail(const char *message)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "embedded PostgreSQL launcher: %s\n", message);
|
||||||
|
exit(127);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void join_path(char *destination, size_t capacity, const char *left, const char *right)
|
||||||
|
{
|
||||||
|
int length = snprintf(destination, capacity, "%s/%s", left, right);
|
||||||
|
if (length < 0 || (size_t) length >= capacity)
|
||||||
|
fail("installation path is too long");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char executable[PATH_MAX];
|
||||||
|
ssize_t executable_length = readlink("/proc/self/exe", executable, sizeof(executable) - 1);
|
||||||
|
if (executable_length < 0) {
|
||||||
|
perror("embedded PostgreSQL launcher: /proc/self/exe");
|
||||||
|
return 127;
|
||||||
|
}
|
||||||
|
executable[executable_length] = '\0';
|
||||||
|
|
||||||
|
char *tool = strrchr(executable, '/');
|
||||||
|
if (tool == NULL || tool[1] == '\0')
|
||||||
|
fail("cannot determine the requested PostgreSQL tool");
|
||||||
|
tool++;
|
||||||
|
|
||||||
|
char root[PATH_MAX];
|
||||||
|
if ((size_t) executable_length >= sizeof(root))
|
||||||
|
fail("installation path is too long");
|
||||||
|
memcpy(root, executable, (size_t) executable_length + 1);
|
||||||
|
|
||||||
|
char *bin_separator = strrchr(root, '/');
|
||||||
|
if (bin_separator == NULL)
|
||||||
|
fail("cannot determine the PostgreSQL installation directory");
|
||||||
|
*bin_separator = '\0';
|
||||||
|
char *root_separator = strrchr(root, '/');
|
||||||
|
if (root_separator == NULL)
|
||||||
|
fail("cannot determine the PostgreSQL installation directory");
|
||||||
|
*root_separator = '\0';
|
||||||
|
|
||||||
|
char loader[PATH_MAX];
|
||||||
|
char library_path[PATH_MAX];
|
||||||
|
char real_tool[PATH_MAX];
|
||||||
|
join_path(loader, sizeof(loader), root, "lib/ld-musl-x86_64.so.1");
|
||||||
|
join_path(library_path, sizeof(library_path), root, "lib");
|
||||||
|
|
||||||
|
char real_tool_relative[PATH_MAX];
|
||||||
|
int relative_length = snprintf(
|
||||||
|
real_tool_relative,
|
||||||
|
sizeof(real_tool_relative),
|
||||||
|
"libexec/%s",
|
||||||
|
tool
|
||||||
|
);
|
||||||
|
if (relative_length < 0 || (size_t) relative_length >= sizeof(real_tool_relative))
|
||||||
|
fail("tool path is too long");
|
||||||
|
join_path(real_tool, sizeof(real_tool), root, real_tool_relative);
|
||||||
|
|
||||||
|
char **loader_argv = calloc((size_t) argc + 6, sizeof(char *));
|
||||||
|
if (loader_argv == NULL) {
|
||||||
|
perror("embedded PostgreSQL launcher: calloc");
|
||||||
|
return 127;
|
||||||
|
}
|
||||||
|
|
||||||
|
loader_argv[0] = loader;
|
||||||
|
loader_argv[1] = "--library-path";
|
||||||
|
loader_argv[2] = library_path;
|
||||||
|
loader_argv[3] = "--argv0";
|
||||||
|
loader_argv[4] = executable;
|
||||||
|
loader_argv[5] = real_tool;
|
||||||
|
for (int index = 1; index < argc; index++)
|
||||||
|
loader_argv[index + 5] = argv[index];
|
||||||
|
|
||||||
|
execv(loader, loader_argv);
|
||||||
|
fprintf(
|
||||||
|
stderr,
|
||||||
|
"embedded PostgreSQL launcher: cannot execute %s: %s\n",
|
||||||
|
real_tool,
|
||||||
|
strerror(errno)
|
||||||
|
);
|
||||||
|
return 127;
|
||||||
|
}
|
||||||
2
server
2
server
Submodule server updated: b79e9a0b57...440e0cf0dc
Reference in New Issue
Block a user