diff --git a/Dockerfile b/Dockerfile index 0a43027..0e9d51a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,22 +12,28 @@ RUN yarn build # production stage FROM alpine:3.15 -ENV USER darkhttpd -ENV GROUP darkhttpd -ENV GID 911 -ENV UID 911 +ENV GID 1000 +ENV UID 1000 ENV PORT 8080 +ENV SUBFOLDER "/_" +ENV INIT_ASSETS 1 -RUN addgroup -S ${GROUP} -g ${GID} && adduser -D -S -u ${UID} ${USER} ${GROUP} && \ - apk add -U --no-cache su-exec darkhttpd +RUN addgroup -S lighttpd -g ${GID} && adduser -D -S -u ${UID} lighttpd lighttpd && \ + apk add -U --no-cache lighttpd -COPY --from=build-stage --chown=${USER}:${GROUP} /app/dist /www/ -COPY --from=build-stage --chown=${USER}:${GROUP} /app/dist/assets /www/default-assets +WORKDIR /www + +COPY lighttpd.conf /lighttpd.conf COPY entrypoint.sh /entrypoint.sh +COPY --from=build-stage --chown=${UID}:${GID} /app/dist /www/ +COPY --from=build-stage --chown=${USER}:${GROUP} /app/dist/assets /www/default-assets + +USER ${UID}:${GID} HEALTHCHECK --interval=30s --timeout=5s --retries=3 \ CMD wget --no-verbose --tries=1 --spider http://127.0.0.1:${PORT}/ || exit 1 EXPOSE ${PORT} VOLUME /www/assets + ENTRYPOINT ["/bin/sh", "/entrypoint.sh"] diff --git a/Dockerfile.arm32v7 b/Dockerfile.arm32v7 index 95a2db1..7e1d92b 100644 --- a/Dockerfile.arm32v7 +++ b/Dockerfile.arm32v7 @@ -21,23 +21,27 @@ FROM arm32v7/alpine:3.11 COPY --from=qemu qemu-arm-static /usr/bin/ -ENV USER darkhttpd -ENV GROUP darkhttpd +ENV USER lighttpd +ENV GROUP lighttpd ENV GID 911 ENV UID 911 ENV PORT 8080 +ENV SUBFOLDER "/_" RUN addgroup -S ${GROUP} -g ${GID} && adduser -D -S -u ${UID} ${USER} ${GROUP} && \ - apk add -U --no-cache darkhttpd su-exec && \ + apk add -U --no-cache lighttpd && \ rm /usr/bin/qemu-arm-static -COPY --from=build-stage --chown=${USER}:${GROUP} /app/dist /www/ -COPY --from=build-stage --chown=${USER}:${GROUP} /app/dist/assets /www/default-assets -COPY entrypoint.sh /entrypoint.sh +WORKDIR /www +COPY lighttpd.conf /lighttpd.conf +COPY --from=build-stage --chown=${USER}:${GROUP} /app/dist /www/ + +USER ${USER} HEALTHCHECK --interval=30s --timeout=5s --retries=3 \ CMD wget --no-verbose --tries=1 --spider http://127.0.0.1:${PORT}/ || exit 1 EXPOSE ${PORT} VOLUME /www/assets -ENTRYPOINT ["/bin/sh", "/entrypoint.sh"] + +CMD ["lighttpd", "-D", "-f", "/lighttpd.conf"] diff --git a/Dockerfile.arm64v8 b/Dockerfile.arm64v8 index cd15e4a..573a2e4 100644 --- a/Dockerfile.arm64v8 +++ b/Dockerfile.arm64v8 @@ -21,23 +21,27 @@ FROM arm64v8/alpine:3.11 COPY --from=qemu qemu-aarch64-static /usr/bin/ -ENV USER darkhttpd -ENV GROUP darkhttpd +ENV USER lighttpd +ENV GROUP lighttpd ENV GID 911 ENV UID 911 ENV PORT 8080 +ENV SUBFOLDER "/_" RUN addgroup -S ${GROUP} -g ${GID} && adduser -D -S -u ${UID} ${USER} ${GROUP} && \ - apk add -U --no-cache darkhttpd su-exec && \ + apk add -U --no-cache lighttpd && \ rm /usr/bin/qemu-aarch64-static -COPY --from=build-stage --chown=${USER}:${GROUP} /app/dist /www/ -COPY --from=build-stage --chown=${USER}:${GROUP} /app/dist/assets /www/default-assets -COPY entrypoint.sh /entrypoint.sh +WORKDIR /www +COPY lighttpd.conf /lighttpd.conf +COPY --from=build-stage --chown=${USER}:${GROUP} /app/dist /www/ + +USER ${USER} HEALTHCHECK --interval=30s --timeout=5s --retries=3 \ CMD wget --no-verbose --tries=1 --spider http://127.0.0.1:${PORT}/ || exit 1 EXPOSE ${PORT} VOLUME /www/assets -ENTRYPOINT ["/bin/sh", "/entrypoint.sh"] + +CMD ["lighttpd", "-D", "-f", "/lighttpd.conf"] diff --git a/README.md b/README.md index 5ea80fb..6ac71e6 100644 --- a/README.md +++ b/README.md @@ -71,8 +71,6 @@ See [documentation](docs/configuration.md) for information about the configurati ### Using docker -To launch container: - ```sh docker run -d \ -p 8080:8080 \ @@ -81,12 +79,19 @@ docker run -d \ b4bz/homer:latest ``` -Default assets will be automatically installed in the `/www/assets` directory. Use `UID` and/or `GID` env var to change the assets owner (`docker run -e "UID=1000" -e "GID=1000" [...]`). +Environment variables: + +* **`INIT_ASSETS`** (default: `1`) +Install exemple configuration file & assets (favicons, ...) to help you get started. + +* **`SUBFOLDER`** (default: `null`) +If you would like to host Homer in a subfolder, (ex: *http://my-domain/**homer***), set this to the subfolder path (ex `/homer`). + ### Using docker-compose The `docker-compose.yml` file must be edited to match your needs. -Set the port and volume (equivalent to `-p` and `-v` arguments): +You probably want to set the port mapping and volume binding (equivalent to `-p` and `-v` arguments): ```yaml volumes: @@ -95,21 +100,13 @@ ports: - 8080:8080 ``` -To launch container: +Then launch the container: ```sh -cd /path/to/docker-compose.yml +cd /path/to/docker-compose.yml/ docker-compose up -d ``` -Default assets will be automatically installed in the `/www/assets` directory. Use `UID` and/or `GID` env var to change the assets owner, also in `docker-compose.yml`: - -```yaml -environment: - - UID=1000 - - GID=1000 -``` - ### Using the release tarball (prebuilt, ready to use) Download and extract the latest release (`homer.zip`) from the [release page](https://github.com/bastienwirtz/homer/releases), rename the `assets/config.yml.dist` file to `assets/config.yml`, and put it behind a web server. diff --git a/docker-compose.yml b/docker-compose.yml index 884703c..231e72a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,7 +10,6 @@ services: - /your/local/assets/:/www/assets ports: - 8080:8080 - #environment: - # - UID=1000 - # - GID=1000 - restart: unless-stopped + user: 1000:1000 # default + environment: + - INIT_ASSETS=1 # default diff --git a/entrypoint.sh b/entrypoint.sh index f1a8c22..eba1cb2 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,15 +1,18 @@ #!/bin/sh -# Ensure default assets are present. -while true; do echo n; done | cp -Ri /www/default-assets/* /www/assets/ &> /dev/null +PERMISSION_ERROR="Check assets directory permissions & docker user or skip default assets install by setting the INIT_ASSETS env var to 0" -# Ensure compatibility with previous version (config.yml was in the root directory) -if [ -f "/www/config.yml" ]; then - yes n | cp -i /www/config.yml /www/assets/ &> /dev/null +# Default assets & exemple configuration installation if possible. +if [[ "${INIT_ASSETS}" == "1" ]] && [[ ! -f "/www/config.yml" ]]; then + echo "No configuration found, installing default config & assets" + if [[ ! -w "/www/assets/" ]]; then echo "Assets directory not writable. $PERMISSION_ERROR" && exit 1; fi + + while true; do echo n; done | cp -Ri /www/default-assets/* /www/assets/ &> /dev/null + if [[ $? -ne 0 ]]; then echo "Fail to copy default assets. $PERMISSION_ERROR" && exit 1; fi + + yes n | cp -i /www/default-assets/config.yml.dist /www/assets/config.yml &> /dev/null + if [[ $? -ne 0 ]]; then echo "Fail to copy default config file. $PERMISSION_ERROR" && exit 1; fi fi -# Install default config if no one is available. -yes n | cp -i /www/default-assets/config.yml.dist /www/assets/config.yml &> /dev/null - -chown -R $UID:$GID /www/assets -exec su-exec $UID:$GID darkhttpd /www/ --no-listing --port "$PORT" +echo "Starting webserver" +lighttpd -D -f /lighttpd.conf diff --git a/lighttpd.conf b/lighttpd.conf new file mode 100644 index 0000000..32e14da --- /dev/null +++ b/lighttpd.conf @@ -0,0 +1,10 @@ +include "/etc/lighttpd/mime-types.conf" + +server.port = env.PORT +server.modules = ( "mod_alias" ) +server.username = "lighttpd" +server.groupname = "lighttpd" +server.document-root = "/www" +alias.url = ( env.SUBFOLDER => "/www" ) +server.indexfiles = ("index.html") +server.follow-symlink = "enable" diff --git a/src/App.vue b/src/App.vue index 81f92f7..515177e 100644 --- a/src/App.vue +++ b/src/App.vue @@ -18,7 +18,10 @@ -
+
{{ config.subtitle }}

{{ config.title }}

@@ -61,7 +64,7 @@ @network-status-update="offline = $event" /> - +
@@ -168,6 +171,7 @@ export default { data: function () { return { loaded: false, + configNotFound: false, config: null, services: null, offline: false, @@ -177,6 +181,11 @@ export default { showMenu: false, }; }, + computed: { + configurationNeeded: function () { + return (this.loaded && !this.services) || this.configNotFound; + }, + }, created: async function () { this.buildDashboard(); window.onhashchange = this.buildDashboard; @@ -228,6 +237,11 @@ export default { return; } + if (response.status == 404) { + this.configNotFound = true; + return {}; + } + if (!response.ok) { throw Error(`${response.statusText}: ${response.body}`); } diff --git a/src/assets/app.scss b/src/assets/app.scss index aa8b077..ae2cb6b 100644 --- a/src/assets/app.scss +++ b/src/assets/app.scss @@ -104,6 +104,10 @@ body { .dashboard-title { padding: 6px 0 0 80px; + + &.no-logo { + padding-left: 0; + } } .first-line { diff --git a/src/components/GetStarted.vue b/src/components/GetStarted.vue index dcabc02..c256a0f 100644 --- a/src/components/GetStarted.vue +++ b/src/components/GetStarted.vue @@ -6,7 +6,7 @@

Get started diff --git a/src/components/services/Emby.vue b/src/components/services/Emby.vue index 25a2612..d2411f0 100644 --- a/src/components/services/Emby.vue +++ b/src/components/services/Emby.vue @@ -62,7 +62,7 @@ export default { this.fetch("/System/info/public") .then((response) => { if (response.Id) this.status = "running"; - else throw new Error(); + else throw new Error(); }) .catch((e) => { console.log(e);