2
0
mirror of https://github.com/spritsail/plex-media-server.git synced 2025-05-05 06:22:29 +00:00

Build Plex on musl, from scratch

Plex now provide a first-party musl Plex build that works without any
external dependencies whatsoever. It's built with LLVM with many
compiler and linker optimisations enabled:
https://forums.plex.tv/t/plex-media-server-forum-preview-faster-and-smaller-builds-with-new-toolchain/699575

Changes for this release include:
- Drop curl, OpenSSL and zlib; they're no longer required. libcurl and
  libssl/libcrypto are provided by Plex anyway.
- Build `FROM spritsail/alpine` instead of `FROM debian` to ensure musl
  compatibility with all compiled binaries. Use `FROM scratch` for the
  resulting image. ld-musl is provided by Plex.
- Build busybox, su-exec and tini as they're no longer provided by the
  base image.
- Build binaries/libraries with standard hardening flags, including the
  popular -flto.

Signed-off-by: Joe Groocock <me@frebib.net>
This commit is contained in:
Joe Groocock 2021-03-13 16:17:21 +00:00
parent f8aef5f2d1
commit 32734c3aa0
Signed by: frebib
GPG Key ID: E0B16BEACFBB6A86
4 changed files with 102 additions and 180 deletions

View File

@ -2,12 +2,6 @@
kind: pipeline kind: pipeline
name: build-amd64 name: build-amd64
trigger:
event:
- push
- pull_request
- tag
platform: platform:
os: linux os: linux
arch: amd64 arch: amd64
@ -24,7 +18,7 @@ steps:
image: spritsail/docker-test image: spritsail/docker-test
settings: settings:
run: | run: |
curl --version && busybox && \
xmlstarlet --version xmlstarlet --version
- name: test - name: test
@ -44,65 +38,15 @@ steps:
settings: settings:
repo: spritsail/plex-media-server repo: spritsail/plex-media-server
tags: tags:
- latest - musl
- "%label io.spritsail.version.plex | %remsuf [0-9a-f]+$ | %auto 2" login: {from_secret: docker_login}
username: {from_secret: docker_username}
password: {from_secret: docker_password}
when: when:
branch: branch:
- master - musl
event: event:
- push - push
---
kind: pipeline
name: update-readme
steps:
- name: dockerhub-readme
pull: always
image: jlesage/drone-push-readme
settings:
username: {from_secret: docker_username}
password: {from_secret: docker_password}
repo: spritsail/plex-media-server
when:
branch:
- master
- pass
event:
- push
---
kind: pipeline
name: update-cron
trigger:
event:
- cron
platform:
os: linux
arch: amd64
steps:
- name: update
pull: always
image: spritsail/alpine
commands:
- apk add bash curl jq git
- ./update.sh
- name: push
pull: always
image: appleboy/drone-git-push
settings:
branch: master
remote: git@github.com:spritsail/plex-media-server.git
ssh_key: {from_secret: git_ssh_key}
--- ---
kind: signature kind: signature
hmac: ffa33c4e8d4d71e4a1dcbc850859ebde679f6c574885d99df3ca9496e1db55b9 hmac: 63bede647ba8e4f4f0a69983c22535fbda0afa811b60830c31edb0fbbf0b8b86
... ...

View File

@ -1,28 +1,49 @@
ARG PLEX_VER=1.21.4.4079-1b7748a7b ARG PLEX_VER=1.22.2.4180-2f337bbd5
ARG PLEX_SHA=081d0ad5dacf455216495e40161be4e45727ceb8 ARG PLEX_SHA=23b53f67e65a4310cb12f3dd6566de5c3224104f
ARG XMLSTAR_VER=1.6.1 ARG XMLSTAR_VER=1.6.1
ARG CURL_VER=curl-7_74_0 ARG BUSYBOX_VER=1.33.0
ARG ZLIB_VER=1.2.11 ARG SU_EXEC_VER=0.4
ARG OPENSSL_VER=1.1.1i ARG TINI_VER=0.19.0
FROM spritsail/debian-builder:buster-slim as builder FROM spritsail/alpine:3.13 AS builder
ARG PLEX_VER ARG PLEX_VER
ARG PLEX_SHA ARG PLEX_SHA
ARG LIBXML2_VER=v2.9.10 ARG LIBXML2_VER=v2.9.10
ARG LIBXSLT_VER=v1.1.34 ARG LIBXSLT_VER=v1.1.34
ARG XMLSTAR_VER ARG XMLSTAR_VER
ARG OPENSSL_VER ARG BUSYBOX_VER
ARG CURL_VER ARG SU_EXEC_VER
ARG ZLIB_VER ARG TINI_VER
ARG MAKEFLAGS ARG MAKEFLAGS
ARG PREFIX=/prefix ARG PREFIX=/prefix
WORKDIR /plex WORKDIR /plex
ENV CFLAGS="-O2 -pipe -fstack-protector-strong -D_FORTIFY_SOURCE=2 -flto" \
CXXFLAGS="${CFLAGS}" \
LDFLAGS="${CFLAGS} -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now"
RUN apk add --no-cache \
autoconf \
automake \
binutils \
cmake \
curl \
dpkg \
file \
gcc \
git \
libtool \
linux-headers \
make \
musl-dev \
pkgconfig \
xxd
# Fetch Plex and required libraries # Fetch Plex and required libraries
RUN curl -fsSL -o plexmediaserver.deb https://downloads.plex.tv/plex-media-server-new/${PLEX_VER}/debian/plexmediaserver_${PLEX_VER}_amd64.deb \ RUN curl -fsSL -o plexmediaserver.deb https://artifacts.plex.tv/testing/pms/${PLEX_VER}/debian/plexmediaserver_${PLEX_VER}_amd64.deb \
&& echo "$PLEX_SHA plexmediaserver.deb" | sha1sum -c - \ && echo "$PLEX_SHA plexmediaserver.deb" | sha1sum -c - \
&& dpkg-deb -x plexmediaserver.deb . \ && dpkg-deb -x plexmediaserver.deb . \
\ \
@ -32,34 +53,51 @@ RUN curl -fsSL -o plexmediaserver.deb https://downloads.plex.tv/plex-media-serve
\ \
&& cd usr/lib/plexmediaserver \ && cd usr/lib/plexmediaserver \
&& rm \ && rm \
lib/libcrypto.so* \
lib/libcurl.so* \
lib/libssl.so* \
lib/libxml2.so* \ lib/libxml2.so* \
lib/libxslt.so* \ lib/libxslt.so* \
lib/libexslt.so* \ lib/libexslt.so* \
lib/plexmediaserver.* \ lib/plexmediaserver.* \
Resources/start.sh \ Resources/start.sh \
\
# Place shared libraries in usr/lib so they can be actually shared # Place shared libraries in usr/lib so they can be actually shared
&& mv lib/*.so* lib/dri ../ \ && mv lib/*.so* lib/dri ../ \
&& rmdir lib \ && rmdir lib \
&& cp /lib/x86_64-linux-gnu/libgcc_s.so.1 ../ && ln -sv ../ lib
# Download and build zlib WORKDIR /tmp/busybox
WORKDIR /tmp/zlib
RUN curl -sSf https://www.zlib.net/zlib-$ZLIB_VER.tar.xz \ # Download and build busybox
| tar xJ --strip-components=1 \ RUN curl -fsSL https://busybox.net/downloads/busybox-${BUSYBOX_VER}.tar.bz2 \
&& ./configure \ | tar xj --strip-components=1 \
--prefix=/usr \ && make defconfig \
--shared \ && make \
&& make DESTDIR=$PREFIX install && install -Dm755 busybox "${PREFIX}/bin/busybox" \
# "Install" busybox, creating symlinks to all binaries it provides
&& mkdir -p "${PREFIX}/bin" "${PREFIX}/sbin" "${PREFIX}/usr/bin" "${PREFIX}/usr/sbin" \
&& ./busybox --list-full | xargs -i ln -Tsv /bin/busybox "${PREFIX}/{}"
WORKDIR /tmp/su-exec
# Download and build su-exec
RUN curl -fL https://github.com/frebib/su-exec/archive/v${SU_EXEC_VER}.tar.gz \
| tar xz --strip-components=1 \
&& make \
&& install -Dm755 su-exec "${PREFIX}/sbin/su-exec"
WORKDIR /tmp/tini
# Download and build tini
RUN curl -fL https://github.com/krallin/tini/archive/v${TINI_VER}.tar.gz \
| tar xz --strip-components=1 \
&& cmake . \
&& make tini \
&& install -Dm755 tini "${PREFIX}/sbin/tini"
# Download and build libxml2 # Download and build libxml2
WORKDIR /tmp/libxml2 WORKDIR /tmp/libxml2
RUN git clone https://gitlab.gnome.org/GNOME/libxml2.git --branch $LIBXML2_VER --depth 1 . \ RUN git clone https://gitlab.gnome.org/GNOME/libxml2.git --branch $LIBXML2_VER --depth 1 . \
&& ./autogen.sh \ && ./autogen.sh \
--prefix=/usr \ --prefix=/usr \
--with-zlib=$PREFIX/usr \
--without-catalog \ --without-catalog \
--without-docbook \ --without-docbook \
--without-ftp \ --without-ftp \
@ -95,99 +133,43 @@ RUN git clone git://git.code.sf.net/p/xmlstar/code --branch $XMLSTAR_VER --depth
--with-libxslt-prefix=$PREFIX/usr \ --with-libxslt-prefix=$PREFIX/usr \
&& make DESTDIR=$PREFIX install && make DESTDIR=$PREFIX install
# Download and build OpenSSL as a cURL dependency
WORKDIR /tmp/openssl
RUN curl -sSL https://openssl.org/source/openssl-${OPENSSL_VER}.tar.gz \
| tar xz --strip-components=1 \
# Install to the default system directories so cURL can find it
&& ./config \
--prefix=/usr \
--libdir=lib \
--with-zlib-lib=$PREFIX/usr/lib/ \
--with-zlib-include=$PREFIX/usr/include \
shared \
zlib-dynamic \
no-rc5 \
no-ssl3-method \
&& make build_libs \
&& make build_programs \
&& make \
install_sw \
install_ssldirs \
&& cp libssl*.so* libcrypto*.so* $PREFIX/usr/lib
# Download and build curl
WORKDIR /tmp/curl
RUN git clone https://github.com/curl/curl.git --branch $CURL_VER --depth 1 . \
&& autoreconf -sif \
&& ./configure \
--prefix=/usr \
--enable-ipv6 \
--enable-optimize \
--enable-symbol-hiding \
--enable-versioned-symbols \
--enable-threaded-resolver \
--with-ssl \
--with-zlib=$PREFIX/usr \
--disable-crypto-auth \
--disable-curldebug \
--disable-dependency-tracking \
--disable-dict \
--disable-gopher \
--disable-imap \
--disable-libcurl-option \
--disable-ldap \
--disable-ldaps \
--disable-manual \
--disable-ntlm-wb \
--disable-pop3 \
--disable-rtsp \
--disable-smb \
--disable-smtp \
--disable-sspi \
--disable-telnet \
--disable-tftp \
--disable-tls-srp \
--disable-verbose \
--without-axtls \
--without-libmetalink \
--without-libpsl \
--without-librtmp \
--without-winidn \
&& make DESTDIR=$PREFIX install
WORKDIR $PREFIX WORKDIR $PREFIX
RUN mkdir -p /output/usr/lib /output/usr/bin /output/etc/ssl/certs \ RUN mkdir -p \
/output/usr/lib \
/output/usr/bin \
/output/usr/sbin \
/output/etc/ssl/certs \
&& install -m 1777 -o root -g root -d /output/tmp \
&& ln -s /usr/lib /usr/bin /usr/sbin /output/ \
# Link Plex ca-certificates as system store so curl and others can use them too # Link Plex ca-certificates as system store so curl and others can use them too
&& ln -sv /usr/lib/plexmediaserver/Resources/cacert.pem /output/etc/ssl/certs/ca-certificates.crt \ && ln -sv /usr/lib/plexmediaserver/Resources/cacert.pem /output/etc/ssl/certs/ca-certificates.crt \
# Move binaries and libraries into their final locations
&& mv usr/lib/*.so* \ && mv usr/lib/*.so* \
/plex/usr/lib/* \ /plex/usr/lib/* \
/output/usr/lib \ /output/usr/lib \
&& mv usr/bin/curl /output/usr/bin \ && mv usr/bin/xml /output/usr/bin/xmlstarlet \
&& mv usr/bin/xml /output/usr/bin/xmlstarlet && mv bin/* usr/bin/* /output/usr/bin \
&& mv sbin/* usr/sbin/* /output/usr/sbin \
# Strip all unneeded symbols for optimum size # Strip all unneeded symbols for optimum size
RUN find /output -exec sh -c 'file "{}" | grep -q ELF && strip --strip-debug "{}"' \; \ && find /output -type f -exec sh -c 'file "{}" | grep -q ELF && strip --strip-debug "{}"' \;
# Disable executable stack in all libraries. This should already be the case
# but it seems libgnsdk is not playing along
&& apt-get -y update \
&& apt-get -y install execstack \
&& execstack -c /output/usr/lib/*.so*
ADD --chmod=755 \ ADD --chmod=755 \
entrypoint \ entrypoint \
*.sh \ claim-server.sh \
/output/usr/local/bin/ gen-config.sh \
plex-util.sh \
/output/usr/bin/
#========================= #=========================
FROM spritsail/busybox:latest FROM scratch
ARG PLEX_VER ARG PLEX_VER
ARG CURL_VER
ARG OPENSSL_VER
ARG XMLSTAR_VER ARG XMLSTAR_VER
ARG BUSYBOX_VER
ARG SU_EXEC_VER
ARG TINI_VER
LABEL maintainer="Spritsail <plex@spritsail.io>" \ LABEL maintainer="Spritsail <plex@spritsail.io>" \
org.label-schema.vendor="Spritsail" \ org.label-schema.vendor="Spritsail" \
@ -196,8 +178,7 @@ LABEL maintainer="Spritsail <plex@spritsail.io>" \
org.label-schema.description="Tiny Docker image for Plex Media Server, built on busybox" \ org.label-schema.description="Tiny Docker image for Plex Media Server, built on busybox" \
org.label-schema.version=${PLEX_VER} \ org.label-schema.version=${PLEX_VER} \
io.spritsail.version.plex=${PLEX_VER} \ io.spritsail.version.plex=${PLEX_VER} \
io.spritsail.version.curl=${CURL_VER} \ io.spritsail.version.busybox=${BUSYBOX_VER} \
io.spritsail.version.openssl=${OPENSSL_VER} \
io.spritsail.version.xmlstarlet=${XMLSTAR_VER} io.spritsail.version.xmlstarlet=${XMLSTAR_VER}
WORKDIR /usr/lib/plexmediaserver WORKDIR /usr/lib/plexmediaserver
@ -222,4 +203,4 @@ RUN mkdir -p "$PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR" \
&& ln -sfv /config "$PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR/Plex Media Server" && ln -sfv /config "$PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR/Plex Media Server"
ENTRYPOINT ["/sbin/tini", "--"] ENTRYPOINT ["/sbin/tini", "--"]
CMD ["/usr/local/bin/entrypoint"] CMD ["/usr/bin/entrypoint"]

View File

@ -13,14 +13,10 @@
[![Build Status](https://drone.spritsail.io/api/badges/spritsail/plex-media-server/status.svg)][drone] [![Build Status](https://drone.spritsail.io/api/badges/spritsail/plex-media-server/status.svg)][drone]
[![Last Build](https://api.spritsail.io/badge/lastbuild/spritsail/plex-media-server:latest)][drone] [![Last Build](https://api.spritsail.io/badge/lastbuild/spritsail/plex-media-server:latest)][drone]
The _smallest*_ Plex Media Server docker image, built on barebones [spritsail/busybox](https://hub.docker.com/r/spritsail/busybox/) with glibc and libraries built from source. The container hosts a fully featured Plex Media Server, with almost all of the useless crap removed, resulting in the smallest container possible whilst maintaining full functionality. The _smallest*_ Plex Media Server docker image, built `FROM scratch` with musl provided by Plex and supporting libraries and binaries built from source. The container hosts a fully featured Plex Media Server, with almost all of the useless crap removed, resulting in the smallest container possible whilst maintaining full functionality.
You can find out more about the [spritsail/busybox](https://hub.docker.com/r/spritsail/busybox) base image [here](https://github.com/spritsail/busybox)
_*last we checked_ _*last we checked_
**NOTICE:** This build has changed the `/config/Plex Media Server` mountpoint inside the container to now be present at `/config`. If you previously used this container, please update your mountpoint to `/config`.
## Getting Started ## Getting Started
Navigate to [plex.tv/claim](https://www.plex.tv/claim) and obtain a token in the form `claim-xxxx...` Navigate to [plex.tv/claim](https://www.plex.tv/claim) and obtain a token in the form `claim-xxxx...`

View File

@ -2,9 +2,9 @@
set -e set -e
# Contains getPref/setPref and PREF_FILE vars # Contains getPref/setPref and PREF_FILE vars
source plex-util.sh . plex-util.sh
opts=`getopt -n "$0" -l save -l token: -l client-id: -l load-client-id -- st:c:l "$@"` || exit 1 opts=$(getopt -n "$0" -l save -l token: -l client-id: -l load-client-id -- st:c:l "$@") || exit 1
eval set -- "$opts" eval set -- "$opts"
while true; do while true; do
case "$1" in case "$1" in
@ -33,16 +33,17 @@ if [ -z "${clientId}" ]; then
fi fi
>&2 echo "Attempting to obtain server token from claim token" >&2 echo "Attempting to obtain server token from claim token"
loginInfo="$(curl -X POST \ loginInfo="$(wget -O- --post-data= \
-H 'X-Plex-Client-Identifier: '${clientId} \ --header "X-Plex-Client-Identifier: ${clientId}" \
-H 'X-Plex-Product: Plex Media Server'\ --header "X-Plex-Product: Plex Media Server" \
-H 'X-Plex-Version: 1.1' \ --header "X-Plex-Version: 1.1" \
-H 'X-Plex-Provides: server' \ --header "X-Plex-Provides: server" \
-H 'X-Plex-Platform: Linux' \ --header "X-Plex-Platform: Linux" \
-H 'X-Plex-Platform-Version: 1.0' \ --header "X-Plex-Platform-Version: 1.0" \
-H 'X-Plex-Device-Name: PlexMediaServer' \ --header "X-Plex-Device-Name: PlexMediaServer" \
-H 'X-Plex-Device: Linux' \ --header "X-Plex-Device: Linux" \
"https://plex.tv/api/claim/exchange?token=${claimToken}")" "https://plex.tv/api/claim/exchange?token=${claimToken}"
)"
authtoken="$(echo "$loginInfo" | sed -n 's/.*<authentication-token>\(.*\)<\/authentication-token>.*/\1/p')" authtoken="$(echo "$loginInfo" | sed -n 's/.*<authentication-token>\(.*\)<\/authentication-token>.*/\1/p')"