Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
[![Blog]({{ lsio_shieldsio_static_blog }})]({{ lsio_blog_url }} "{{ lsio_blog_desc }}")
[![Discord]({{ lsio_shieldsio_discord }})]({{ lsio_discord_url }} "{{ lsio_discord_desc }}")
[![Discourse]({{ lsio_shieldsio_discourse_topics }})]({{ lsio_discourse_url }} "{{ lsio_discourse_desc }}")
[![Fleet]({{ lsio_shieldsio_static_fleet }})]({{ lsio_fleet_url }} "{{ lsio_fleet_desc }}")
[![GitHub]({{ lsio_shieldsio_static_github }})]({{ lsio_github_url }} "{{ lsio_github_desc }}")
[![Open Collective]({{ lsio_shieldsio_opencollective_all }})]({{ lsio_opencollective_url }} "{{ lsio_opencollective_desc }}")
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,5 @@ Find us at:
* [Blog]({{ lsio_blog_url }}) - {{ lsio_blog_desc }}
* [Discord]({{ lsio_discord_url }}) - {{ lsio_discord_desc }}
* [Discourse]({{ lsio_discourse_url }}) - {{ lsio_discourse_desc }}
* [Fleet]({{ lsio_fleet_url }}) - {{ lsio_fleet_desc }}
* [GitHub]({{ lsio_github_url }}) - {{ lsio_github_desc }}
* [Open Collective]({{ lsio_opencollective_url }}) - {{ lsio_opencollective_desc }}
117 changes: 117 additions & 0 deletions ansible/roles/documentation/templates/README_SNIPPETS/SELKIES.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
**Modern GUI desktop apps may have compatibility issues with the latest Docker syscall restrictions. You can use Docker with the `--security-opt seccomp=unconfined` setting to allow these syscalls on hosts with older Kernels or libseccomp versions.**

### Security

{{ "This container provides privileged access to the host system. Do not expose it to the Internet unless you have secured it properly." | admonition(flavour=markdown, severity="warning") }}

**HTTPS is required for full functionality.** Modern browser features such as WebCodecs, used for video and audio, will not function over an insecure HTTP connection.

By default, this container has no authentication. The optional `CUSTOM_USER` and `PASSWORD` environment variables enable basic HTTP auth, which is suitable only for securing the container on a trusted local network. For internet exposure, we strongly recommend placing the container behind a reverse proxy, such as [SWAG](https://github.com/linuxserver/docker-swag), with a robust authentication mechanism.

The web interface includes a terminal with passwordless `sudo` access. Any user with access to the GUI can gain root control within the container, install arbitrary software, and probe your local network.

### Options in all Selkies-based GUI containers

This container is based on [Docker Baseimage Selkies](https://github.com/linuxserver/docker-baseimage-selkies), which provides the following environment variables and run configurations to customize its functionality.

#### Optional Environment Variables

| Variable | Description |
| :----: | --- |
| `CUSTOM_PORT` | Internal HTTP port. Defaults to `{% if external_http_port is defined %}{{ external_http_port }}{% else %}3000{% endif %}`. |
| `CUSTOM_HTTPS_PORT` | Internal HTTPS port. Defaults to `{% if external_https_port is defined %}{{ external_https_port }}{% else %}3001{% endif %}`. |
| `CUSTOM_USER` | Username for HTTP Basic Auth. Defaults to `abc`. |
| `PASSWORD` | Password for HTTP Basic Auth. If unset, authentication is disabled. |
| `SUBFOLDER` | Application subfolder for reverse proxy configurations. Must include leading and trailing slashes, e.g., `/subfolder/`. |
| `TITLE` | Page title displayed in the web browser. Defaults to "Selkies". |
| `START_DOCKER` | If set to `false`, the privileged Docker-in-Docker setup will not start automatically. |
| `DISABLE_IPV6` | Set to `true` to disable IPv6 support in the container. |
| `LC_ALL` | Sets the container's locale, e.g., `fr_FR.UTF-8`. |
| `NO_DECOR` | If set, applications will run without window borders, suitable for PWA usage. |
| `NO_FULL` | If set, applications will not be automatically fullscreened. |
| `DISABLE_ZINK` | If set, Zink-related environment variables will not be configured when a video card is detected. |
| `WATERMARK_PNG` | Full path to a watermark PNG file inside the container, e.g., `/usr/share/selkies/www/icon.png`. |
| `WATERMARK_LOCATION` | Integer specifying the watermark location: `1` (Top Left), `2` (Top Right), `3` (Bottom Left), `4` (Bottom Right), `5` (Centered), `6` (Animated). |

#### Optional Run Configurations

| Argument | Description |
| :----: | --- |
| `--privileged` | Starts a Docker-in-Docker (DinD) environment. For better performance, mount the Docker data directory from the host, e.g., `-v /path/to/docker-data:/var/lib/docker`. |
| `-v /var/run/docker.sock:/var/run/docker.sock` | Mounts the host's Docker socket to manage host containers from within this container. |

### Language Support - Internationalization

To launch the desktop session in a different language, set the `LC_ALL` environment variable. For example:

* `-e LC_ALL=zh_CN.UTF-8` - Chinese
* `-e LC_ALL=ja_JP.UTF-8` - Japanese
* `-e LC_ALL=ko_KR.UTF-8` - Korean
* `-e LC_ALL=ar_AE.UTF-8` - Arabic
* `-e LC_ALL=ru_RU.UTF-8` - Russian
* `-e LC_ALL=es_MX.UTF-8` - Spanish (Latin America)
* `-e LC_ALL=de_DE.UTF-8` - German
* `-e LC_ALL=fr_FR.UTF-8` - French
* `-e LC_ALL=nl_NL.UTF-8` - Netherlands
* `-e LC_ALL=it_IT.UTF-8` - Italian

{% if show_nvidia is defined %}### Nvidia GPU Support

**Note: Nvidia support is not available for Alpine-based images.**

Nvidia GPU support is available by leveraging Zink for OpenGL. When a compatible Nvidia GPU is passed through, it will also be **automatically utilized for hardware-accelerated video stream encoding** (using the `x264enc` full-frame profile), significantly reducing CPU load.

Enable Nvidia support with the following runtime flags:

| Flag | Description |
| :----: | --- |
| `--gpus all` | Passes all available host GPUs to the container. This can be filtered to specific GPUs. |
| `--runtime nvidia` | Specifies the Nvidia runtime, which provides the necessary drivers and tools from the host. |

For Docker Compose, you must first configure the Nvidia runtime as the default on the host:

```
sudo nvidia-ctk runtime configure --runtime=docker --set-as-default
sudo systemctl restart docker
```

Then, assign the GPU to the service in your `compose.yaml`:

```
services:
{{ project_name }}:
image: lscr.io/{{ lsio_project_name_short }}/{{ project_name }}:{{ release_tag }}
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [compute,video,graphics,utility]
```

{% endif %}### Application Management

There are two methods for installing applications inside the container: PRoot Apps (recommended for persistence) and Native Apps.

#### PRoot Apps (Persistent)

Natively installed packages (e.g., via `apt-get install`) will not persist if the container is recreated. To retain applications and their settings across container updates, we recommend using [proot-apps](https://github.com/linuxserver/proot-apps). These are portable applications installed to the user's persistent `$HOME` directory.

To install an application, use the command line inside the container:

```
proot-apps install filezilla
```

A list of supported applications is available [here](https://github.com/linuxserver/proot-apps?tab=readme-ov-file#supported-apps).

#### Native Apps (Non-Persistent)

You can install packages from the system's native repository using the [universal-package-install](https://github.com/linuxserver/docker-mods/tree/universal-package-install) mod. This method will increase the container's start time and is not persistent. Add the following to your `compose.yaml`:

```yaml
environment:
- DOCKER_MODS=linuxserver/mods:universal-package-install
- INSTALL_PACKAGES=libfuse2|git|gdb
```
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,3 @@ The architectures supported by this image are:
| riscv64 | {{ '✅ | riscv64-\<version tag\>' }} |
{% endif %}
| arm64 | {{ '✅ | arm64v8-\<version tag\>' if 'arm64' in (available_architectures | map(attribute="arch") ) else '❌ |' }} |
| armhf | {{ '✅ | arm32v7-\<version tag\>' if 'armhf' in (available_architectures | map(attribute="arch") ) else '❌ |' }} |
4 changes: 4 additions & 0 deletions ansible/roles/documentation/templates/documentation.md.j2
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ description: "{{ noter(project_blurb) | trim }}"
{% if kasm_blurb is defined %}
{% include "README_SNIPPETS/KASM.j2" | trim %}

{% endif %}
{% if selkies_blurb is defined %}
{% include "README_SNIPPETS/SELKIES.j2" | trim %}

{% endif %}
{% if readonly_supported is defined and readonly_supported %}
{% include "README_SNIPPETS/READONLY.j2" | trim %}
Expand Down
4 changes: 4 additions & 0 deletions ansible/roles/documentation/templates/readme.md.j2
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@
{% if kasm_blurb is defined %}
{% include "README_SNIPPETS/KASM.j2" | trim %}

{% endif %}
{% if selkies_blurb is defined %}
{% include "README_SNIPPETS/SELKIES.j2" | trim %}

{% endif %}
{% if readonly_supported is defined and readonly_supported %}
{% include "README_SNIPPETS/READONLY.j2" | trim %}
Expand Down
16 changes: 11 additions & 5 deletions ansible/roles/documentation/templates/unraid.xml.j2
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,19 @@
{# Set the WebUI link based on the link the CI runs against #}
<TemplateURL>{{ "false" if unraid_template_sync is sameas false else "https://raw.githubusercontent.com/linuxserver/templates/main/unraid/" + project_name | lower + ".xml" }}</TemplateURL>
<Icon>https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/linuxserver-ls-logo.png</Icon>
{% if (unraid_requirement is defined and unraid_requirement != "") or (external_application_snippet_enabled) %}
{% if (unraid_requirement is defined and unraid_requirement != "") or (external_application_snippet_enabled) or (selkies_blurb is defined) %}
<Requires>
{{ unraid_requirement }}
{% if external_application_snippet_enabled %}
{% if unraid_requirement is defined %}
{{ unraid_requirement | indent(4) | trim }}
{% endif %}
{% if external_application_snippet_enabled %}
This container requires an external application to be run separately.
{{ external_application_unraid_block }}
{% endif %}
{{ external_application_unraid_block | indent(4) | trim }}
{% endif %}
{% if selkies_blurb is defined %}
This image is unprotected by default __**do not**__ expose it to the internet.
Please read {{ project_github_repo_url }}#security for more information.
{% endif %}
</Requires>
{% endif %}
{# Create changelog #}
Expand Down
3 changes: 3 additions & 0 deletions ansible/roles/github/templates/call_issue_pr_tracker.yml.j2
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ on:
pull_request_review:
types: [submitted,edited,dismissed]

permissions:
contents: read

jobs:
manage-project:
permissions:
Expand Down
3 changes: 3 additions & 0 deletions ansible/roles/github/templates/call_issues_cron.yml.j2
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ on:
- cron: '{{ 60 | random(seed=('docker-' + project_name + '-minute')) }} {{ 24 | random(seed=('docker-' + project_name + '-hour')) }} * * *'
workflow_dispatch:

permissions:
contents: read

jobs:
stale:
permissions:
Expand Down
15 changes: 9 additions & 6 deletions ansible/roles/github/templates/external_trigger.yml.j2
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ name: External Trigger Main
on:
workflow_dispatch:

permissions:
contents: read

jobs:
external-trigger-{{ ls_branch|regex_replace('[^a-zA-Z0-9-]','-') }}:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -107,8 +110,8 @@ jobs:
"username": "Github Actions"}' ${{ '{{' }} secrets.DISCORD_WEBHOOK {{ '}}' }}
exit 1
fi
EXT_RELEASE=$(echo ${EXT_RELEASE} | sed 's/[~,%@+;:/]//g')
echo "External version: \`${EXT_RELEASE}\`" >> $GITHUB_STEP_SUMMARY
EXT_RELEASE_SANITIZED=$(echo ${EXT_RELEASE} | sed 's/[~,%@+;:/]//g')
echo "Sanitized external version: \`${EXT_RELEASE_SANITIZED}\`" >> $GITHUB_STEP_SUMMARY
echo "Retrieving last pushed version" >> $GITHUB_STEP_SUMMARY
image="{{ better_vars.LS_USER }}/{{ project_name }}"
tag="{{ release_tag }}"
Expand Down Expand Up @@ -164,8 +167,8 @@ jobs:
exit 1
fi
echo "Last pushed version: \`${IMAGE_VERSION}\`" >> $GITHUB_STEP_SUMMARY
if [ "${EXT_RELEASE}" == "${IMAGE_VERSION}" ]; then
echo "Version \`${EXT_RELEASE}\` already pushed, exiting" >> $GITHUB_STEP_SUMMARY
if [ "${EXT_RELEASE_SANITIZED}" == "${IMAGE_VERSION}" ]; then
echo "Sanitized version \`${EXT_RELEASE_SANITIZED}\` already pushed, exiting" >> $GITHUB_STEP_SUMMARY
exit 0
{% if external_type == "alpine_repo" and better_vars.MULTIARCH == 'true' %}
elif [[ $(curl -sL "{{ better_vars.DIST_REPO }}aarch64/APKINDEX.tar.gz" | tar -xz -C /tmp && awk '/^P:'"{{ better_vars.DIST_REPO_PACKAGES }}"'$/,/V:/' /tmp/APKINDEX | sed -n 2p | sed 's/^V://') != "${EXT_RELEASE}" ]]{% if build_armhf %} || [[ $(curl -sL "{{ better_vars.DIST_REPO }}armv7/APKINDEX.tar.gz" | tar -xz -C /tmp && awk '/^P:'"{{ better_vars.DIST_REPO_PACKAGES }}"'$/,/V:/' /tmp/APKINDEX | sed -n 2p | sed 's/^V://') != "${EXT_RELEASE}" ]]{% endif %}; then
Expand Down Expand Up @@ -197,7 +200,7 @@ jobs:
"username": "Github Actions"}' ${{ '{{' }} secrets.DISCORD_WEBHOOK {{ '}}' }}
else
printf "\n## Trigger new build\n\n" >> $GITHUB_STEP_SUMMARY
echo "New version \`${EXT_RELEASE}\` found; old version was \`${IMAGE_VERSION}\`. Triggering new build" >> $GITHUB_STEP_SUMMARY
echo "New sanitized version \`${EXT_RELEASE_SANITIZED}\` found; old version was \`${IMAGE_VERSION}\`. Triggering new build" >> $GITHUB_STEP_SUMMARY
if [[ "${artifacts_found}" == "true" ]]; then
echo "All artifacts seem to be uploaded." >> $GITHUB_STEP_SUMMARY
fi
Expand All @@ -217,7 +220,7 @@ jobs:
--data-urlencode "description=GHA external trigger https://github.com/${{ '{{' }} github.repository {{ '}}' }}/actions/runs/${{ '{{' }} github.run_id {{ '}}' }}" \
--data-urlencode "Submit=Submit"
echo "**** Notifying Discord ****"
TRIGGER_REASON="A version change was detected for {{ project_name }} tag {{ release_tag }}. Old version:${IMAGE_VERSION} New version:${EXT_RELEASE}"
TRIGGER_REASON="A version change was detected for {{ project_name }} tag {{ release_tag }}. Old version:${IMAGE_VERSION} New version:${EXT_RELEASE_SANITIZED}"
curl -X POST -H "Content-Type: application/json" --data '{"avatar_url": "https://cdn.discordapp.com/avatars/354986384542662657/df91181b3f1cf0ef1592fbe18e0962d7.png","embeds": [{"color": 9802903,
"description": "**Build Triggered** \n**Reason:** '"${TRIGGER_REASON}"' \n**Build URL:** '"${buildurl}display/redirect"' \n"}],
"username": "Github Actions"}' ${{ '{{' }} secrets.DISCORD_WEBHOOK {{ '}}' }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ on:
- cron: '{{ 60 | random(seed=(project_name + '-external-minute')) }} * * * *'
workflow_dispatch:

permissions:
contents: read

jobs:
external-trigger-scheduler:
runs-on: ubuntu-latest
Expand Down
6 changes: 6 additions & 0 deletions ansible/roles/github/templates/greetings.yml.j2
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@ name: Greetings

on: [pull_request_target, issues]

permissions:
contents: read

jobs:
greeting:
permissions:
issues: write
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/first-interaction@v1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ on:
- cron: '{{ 60 | random(seed=(project_name + '-minute')) }} {{ 24 | random(seed=(project_name + '-hour')) }} * * {{ 7 | random(seed=(project_name + '-day')) }}'
workflow_dispatch:

permissions:
contents: read

jobs:
package-trigger-scheduler:
runs-on: ubuntu-latest
Expand Down
7 changes: 6 additions & 1 deletion ansible/roles/repository/templates/Jenkinsfile.j2
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,11 @@ pipeline {
env.DOCKERHUB_LINK = 'https://hub.docker.com/r/' + env.DOCKERHUB_IMAGE + '/tags/'
env.PULL_REQUEST = env.CHANGE_ID
env.TEMPLATED_FILES = 'Jenkinsfile README.md LICENSE .editorconfig ./.github/CONTRIBUTING.md ./.github/FUNDING.yml ./.github/ISSUE_TEMPLATE/config.yml ./.github/ISSUE_TEMPLATE/issue.bug.yml ./.github/ISSUE_TEMPLATE/issue.feature.yml ./.github/PULL_REQUEST_TEMPLATE.md{% if project_deprecation_status != true %} ./.github/workflows/external_trigger_scheduler.yml ./.github/workflows/greetings.yml ./.github/workflows/package_trigger_scheduler.yml ./.github/workflows/call_issue_pr_tracker.yml ./.github/workflows/call_issues_cron.yml ./.github/workflows/permissions.yml{% if custom_external_trigger != true %} ./.github/workflows/external_trigger.yml{% endif %}{% endif %}{% if sponsor_links is defined %} ./root/donate.txt{% endif %}{% if project_deprecation_status %} ./root/etc/s6-overlay/s6-rc.d/init-deprecate/run ./root/etc/s6-overlay/s6-rc.d/init-deprecate/up ./root/etc/s6-overlay/s6-rc.d/init-deprecate/type ./root/etc/s6-overlay/s6-rc.d/init-deprecate/dependencies.d/init-config-end ./root/etc/s6-overlay/s6-rc.d/init-services/dependencies.d/init-deprecate ./root/etc/s6-overlay/s6-rc.d/user/contents.d/init-deprecate{% endif %}'
if ( env.SYFT_IMAGE_TAG == null ) {
env.SYFT_IMAGE_TAG = 'latest'
}
}
echo "Using syft image tag ${SYFT_IMAGE_TAG}"
sh '''#! /bin/bash
echo "The default github branch detected as ${GH_DEFAULT_BRANCH}" '''
script{
Expand Down Expand Up @@ -1082,7 +1086,7 @@ pipeline {
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v ${TEMPDIR}:/tmp \
ghcr.io/anchore/syft:v1.26.1 \
ghcr.io/anchore/syft:${SYFT_IMAGE_TAG} \
${LOCAL_CONTAINER} -o table=/tmp/package_versions.txt
NEW_PACKAGE_TAG=$(md5sum ${TEMPDIR}/package_versions.txt | cut -c1-8 )
echo "Package tag sha from current packages in buit container is ${NEW_PACKAGE_TAG} comparing to old ${PACKAGE_TAG} from github"
Expand Down Expand Up @@ -1210,6 +1214,7 @@ pipeline {
-e WEB_AUTH=\"${CI_AUTH}\" \
-e WEB_PATH=\"${CI_WEBPATH}\" \
-e NODE_NAME=\"${NODE_NAME}\" \
-e SYFT_IMAGE_TAG=\"${CI_SYFT_IMAGE_TAG:${SYFT_IMAGE_TAG}}\" \
-t ghcr.io/linuxserver/ci:latest \
python3 test_build.py'''
}
Expand Down
3 changes: 0 additions & 3 deletions ansible/vars/common.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ lsio_discord_url: "https://linuxserver.io/discord"
lsio_discourse_url: "https://discourse.{{ lsio_short_url }}"
lsio_docker_hub_url: "https://hub.docker.com/r/{{ lsio_project_name_short }}"
lsio_docs_url: "https://docs.{{ lsio_short_url }}"
lsio_fleet_url: "https://fleet.{{ lsio_short_url }}"
lsio_github_url: "https://github.com/{{ lsio_project_name_short }}"
lsio_gitlab_url: "https://gitlab.com/{{ lsio_project_name }}"
lsio_mods_url: "https://mods.{{ lsio_short_url }}/?mod={{ project_name }}"
Expand All @@ -38,7 +37,6 @@ arch_armhf: "armhf"
lsio_blog_desc: "all the things you can do with our containers including How-To guides, opinions and much more!"
lsio_discord_desc: "realtime support / chat with the community and the team."
lsio_discourse_desc: "post on our community forum."
lsio_fleet_desc: "an online web interface which displays all of our maintained images."
lsio_github_desc: "view the source for all of our repositories."
lsio_mods_desc: "view available mods for this container."
lsio_universal_mods_desc: "view available universal mods."
Expand Down Expand Up @@ -72,7 +70,6 @@ lsio_shieldsio_jenkins_build: "https://img.shields.io/jenkins/build?{{ lsio_badg
lsio_shieldsio_microbadger_layers: "https://img.shields.io/microbadger/layers/{{ lsio_project_name_short }}/{{ project_name }}.svg?{{ lsio_badge_url_parameters }}"
lsio_shieldsio_opencollective_all: "https://img.shields.io/opencollective/all/{{ lsio_project_name_short }}.svg?{{ lsio_badge_url_parameters }}&label=Supporters&logo=open%20collective"
lsio_shieldsio_static_blog: "https://img.shields.io/static/v1.svg?{{ lsio_badge_url_parameters }}&label={{ lsio_project_name }}&message=Blog"
lsio_shieldsio_static_fleet: "https://img.shields.io/static/v1.svg?{{ lsio_badge_url_parameters }}&label={{ lsio_project_name }}&message=Fleet"
lsio_shieldsio_static_github_package: "https://img.shields.io/static/v1.svg?{{ lsio_badge_url_parameters }}&label={{ lsio_project_name }}&message=GitHub%20Package&logo=github"
lsio_shieldsio_static_github: "https://img.shields.io/static/v1.svg?{{ lsio_badge_url_parameters }}&label={{ lsio_project_name }}&message=GitHub&logo=github"
lsio_shieldsio_static_gitlab_registry: "https://img.shields.io/static/v1.svg?{{ lsio_badge_url_parameters }}&label={{ lsio_project_name }}&message=GitLab%20Registry&logo=gitlab"
Expand Down