Compare commits
206 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
96d318ebd0 | ||
|
|
8b11bca749 | ||
|
|
9d43f152b9 | ||
|
|
0dd343aea9 | ||
|
|
37f7280dba | ||
|
|
7552680a01 | ||
|
|
9a460b27e6 | ||
|
|
c452e67fd7 | ||
|
|
22cf7e5980 | ||
|
|
20c6b515ed | ||
|
|
ae88645245 | ||
|
|
868def8906 | ||
|
|
5cef857d34 | ||
|
|
b5cb3fb0db | ||
|
|
3867701a6b | ||
|
|
35722dfa84 | ||
|
|
acee2481c1 | ||
|
|
cc8bc1b02d | ||
|
|
cb751f5a80 | ||
|
|
aa1edd48e0 | ||
|
|
771c47d602 | ||
|
|
0981af0a17 | ||
|
|
608f772ccc | ||
|
|
60fa2363eb | ||
|
|
7513c19bfd | ||
|
|
e4cf09dcb0 | ||
|
|
3cce8f79f8 | ||
|
|
90510bd8ea | ||
|
|
c8d613da5b | ||
|
|
63137d43ec | ||
|
|
3faf8df134 | ||
|
|
c3480448ff | ||
|
|
e0dc046470 | ||
|
|
269e71a0db | ||
|
|
97613b227f | ||
|
|
39d4ce0a0c | ||
|
|
b7bb479635 | ||
|
|
b89e2f565d | ||
|
|
1b7873833c | ||
|
|
890b9d22d2 | ||
|
|
2f118e4a51 | ||
|
|
dd3f079d71 | ||
|
|
c925ff8c87 | ||
|
|
aea4d51159 | ||
|
|
1454b704a2 | ||
|
|
d899ebd965 | ||
|
|
b51036a697 | ||
|
|
8ad830d5e4 | ||
|
|
2c8f6150e9 | ||
|
|
6be269a3bb | ||
|
|
ee4fd33e72 | ||
|
|
c671ba85cc | ||
|
|
4f94568262 | ||
|
|
fed3000700 | ||
|
|
c731e2e0a0 | ||
|
|
02a94566b2 | ||
|
|
5837843aa2 | ||
|
|
ac7dc533e7 | ||
|
|
577d0ef299 | ||
|
|
ca5821774b | ||
|
|
edab557c20 | ||
|
|
0414726448 | ||
|
|
d2b4d2cae7 | ||
|
|
53af510b45 | ||
|
|
cfeb39c268 | ||
|
|
6913938585 | ||
|
|
9c3497d73a | ||
|
|
658b18a634 | ||
|
|
d386c282e6 | ||
|
|
af1c17fdfd | ||
|
|
b75b496283 | ||
|
|
659bde74f5 | ||
|
|
23c5df2996 | ||
|
|
9fe592672a | ||
|
|
932e15314a | ||
|
|
3be80a920e | ||
|
|
35de069bf1 | ||
|
|
8da0bd023d | ||
|
|
26b775f66e | ||
|
|
555bd8991d | ||
|
|
42ebc826b8 | ||
|
|
0b600108f7 | ||
|
|
8d43f93b55 | ||
|
|
f92fb55290 | ||
|
|
417ab4488b | ||
|
|
fc700e2200 | ||
|
|
df9423ccad | ||
|
|
68244060ff | ||
|
|
8c6051aec7 | ||
|
|
4896a5bc36 | ||
|
|
5577410923 | ||
|
|
6a2d55196b | ||
|
|
98a4425fce | ||
|
|
d4e7048745 | ||
|
|
7505ef3b23 | ||
|
|
9b962580ff | ||
|
|
0d2da789ef | ||
|
|
2c5da29701 | ||
|
|
d893d9565c | ||
|
|
81e378e9d0 | ||
|
|
595e60182b | ||
|
|
6b587427b2 | ||
|
|
91e414b341 | ||
|
|
07fe21bb1c | ||
|
|
2e9a20a87a | ||
|
|
3b9311fde3 | ||
|
|
54e4e09d29 | ||
|
|
5fa3f2b968 | ||
|
|
45f73da6cb | ||
|
|
72f2543b02 | ||
|
|
03beff3ff3 | ||
|
|
4b7cf66ecf | ||
|
|
9712eede91 | ||
|
|
477e25f82c | ||
|
|
f233991597 | ||
|
|
1fbfd235f1 | ||
|
|
469b12087d | ||
|
|
54911cb97b | ||
|
|
93fb8f858c | ||
|
|
1e255f822d | ||
|
|
829754b8fb | ||
|
|
a80eda6086 | ||
|
|
341c05cecd | ||
|
|
99f9034766 | ||
|
|
703be17214 | ||
|
|
db070cce96 | ||
|
|
4441b79b1e | ||
|
|
7b620c7918 | ||
|
|
145d5600a6 | ||
|
|
2c0b7b5d53 | ||
|
|
7614e503a7 | ||
|
|
cfd7bbda0e | ||
|
|
1cc4257dd5 | ||
|
|
30699db581 | ||
|
|
c6ccb39b13 | ||
|
|
c63e9ac0b9 | ||
|
|
c2abf14dd3 | ||
|
|
6340f4113e | ||
|
|
38d9442c7d | ||
|
|
686f76bc95 | ||
|
|
a3294eb582 | ||
|
|
b088a7adf4 | ||
|
|
9bfc3568e6 | ||
|
|
cb597e4423 | ||
|
|
f9149958bb | ||
|
|
adac278106 | ||
|
|
8b1de46a6d | ||
|
|
6260809ab3 | ||
|
|
f4734507bf | ||
|
|
5d2ece84dc | ||
|
|
444cfae3fa | ||
|
|
5d0ce361ce | ||
|
|
b21607c4b5 | ||
|
|
becf1c586b | ||
|
|
3a6178979f | ||
|
|
ae818f3080 | ||
|
|
6fe1845a1e | ||
|
|
787035fb21 | ||
|
|
234daf876b | ||
|
|
79cb946b01 | ||
|
|
e5bd4be2f9 | ||
|
|
42534b2e15 | ||
|
|
ba01d6f523 | ||
|
|
63d2f726a5 | ||
|
|
d49bee6547 | ||
|
|
6dce17ac84 | ||
|
|
4f1a693b88 | ||
|
|
576bf9471c | ||
|
|
75c2df3115 | ||
|
|
168c46ae72 | ||
|
|
73a4af0f5c | ||
|
|
74871da011 | ||
|
|
c8dde58c9a | ||
|
|
7056a225d5 | ||
|
|
552714c75f | ||
|
|
5213e1c9f7 | ||
|
|
68b5d3df3c | ||
|
|
3aa0d04d91 | ||
|
|
217d0eb26e | ||
|
|
641a7ae7a7 | ||
|
|
a1a05675e3 | ||
|
|
f0ab202711 | ||
|
|
ada5d2a9dc | ||
|
|
8fc06d9621 | ||
|
|
090c274a55 | ||
|
|
494d0f37e3 | ||
|
|
09c2ea2109 | ||
|
|
d06582c38e | ||
|
|
8d90694712 | ||
|
|
96f4476069 | ||
|
|
bb742d5b96 | ||
|
|
61cc30d69b | ||
|
|
1f5bfcd86a | ||
|
|
57641f7536 | ||
|
|
ba3f96c5fd | ||
|
|
963f3d553f | ||
|
|
9d7b27066c | ||
|
|
446a043703 | ||
|
|
89e85397dd | ||
|
|
07c6ebc967 | ||
|
|
ba277817a0 | ||
|
|
14871dcecd | ||
|
|
ad9cbb9bca | ||
|
|
0008e05848 | ||
|
|
1ba89a9bc8 | ||
|
|
8e877e3762 |
@@ -1 +1,2 @@
|
||||
config
|
||||
devops
|
||||
|
||||
87
.github/ISSUE_TEMPLATE/BUG-REPORT.yml
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
---
|
||||
|
||||
name: Bug Report
|
||||
description: Please do not use bug reports for support issues.
|
||||
title: "[Bug]: "
|
||||
labels: ['status:awaiting-triage', 'type:bug']
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
**THIS IS NOT THE PLACE TO ASK FOR SUPPORT!** Please use [Discord](https://unmanic.app/discord) for support issues.
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Describe the Bug
|
||||
description: A clear and concise description of the bug.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: steps
|
||||
attributes:
|
||||
label: Steps to Reproduce
|
||||
description: List each action required in order to reproduce the issue.
|
||||
placeholder: |
|
||||
1. First Step '...'
|
||||
2. Second Step '...'
|
||||
3. So on '...'
|
||||
4. See error
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: A clear and concise description of what you expected to happen.
|
||||
- type: textarea
|
||||
id: screenshots
|
||||
attributes:
|
||||
label: Screenshots
|
||||
description: Provide screenshots to help explain your problem.
|
||||
- type: textarea
|
||||
id: relevant
|
||||
attributes:
|
||||
label: Relevant Settings
|
||||
description: Include all settings/configuration that are relevant to your setup.
|
||||
placeholder: |
|
||||
- eg. Configuration of your Docker container.
|
||||
- eg. Configurations within the application/container.
|
||||
- eg. External processes that you have connected to or communicating with the application/container.
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: The version is the first line printed in the Docker log.
|
||||
placeholder: 'Build: [10/08/22 03:09:26] [master] [477e25f82c2612b6345ca0c9777345e6b5129965]'
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: platform
|
||||
attributes:
|
||||
label: Platform
|
||||
description: |
|
||||
Detail the host OS platform, version and software versions.
|
||||
- Distribution: `$(. /etc/os-release; echo "${NAME} - ${VERSION}")`
|
||||
- Linux Kernel: `$(uname -rpio)`
|
||||
- GPU Driver versions: `$(nvidia-smi | grep 'Version:')`
|
||||
- Docker: `$(docker -v)`
|
||||
- Docker-compose: `$(docker compose -v)`
|
||||
placeholder: |
|
||||
- Distribution:
|
||||
- Linux Kernel:
|
||||
- GPU Driver versions:
|
||||
- Docker:
|
||||
- Docker-compose:
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: |
|
||||
Please copy and paste any relevant log output.
|
||||
This will be automatically formatted into code, so no need for backticks.
|
||||
Note: Most relevant logs are found either in the docker logs or inside the container in /home/default/.cache/log/
|
||||
render: Shell
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Make sure to close your issue when it's solved! If you found the solution yourself please comment so that others benefit from it.
|
||||
17
.github/ISSUE_TEMPLATE/DOCUMENTATION.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
|
||||
name: Documentation Improvement
|
||||
description: Suggest an update to documentation.
|
||||
labels: ['status:awaiting-triage', 'type:documentation']
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to help improve!
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: Provide a description of the proposed changes.
|
||||
validations:
|
||||
required: true
|
||||
33
.github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
|
||||
name: Feature Request
|
||||
description: Suggest a new feature.
|
||||
labels: ['status:awaiting-triage', 'type:enhancement']
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to help improve!
|
||||
- type: textarea
|
||||
id: problem
|
||||
attributes:
|
||||
label: Is your feature request related to a problem?
|
||||
description: If so, please provide clear and concise description of the problem.
|
||||
placeholder: eg. I'm always frustrated when '...'
|
||||
- type: textarea
|
||||
id: feature
|
||||
attributes:
|
||||
label: What is your feature request?
|
||||
description: A clear and concise description of the feature.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: workaround
|
||||
attributes:
|
||||
label: Are there any workarounds?
|
||||
description: A clear and concise description of any alternative solutions or features you've considered.
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: Add any other context or screenshots about the feature request here.
|
||||
10
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Discord support
|
||||
url: https://unmanic.app/discord
|
||||
about: Ask questions in Discord.
|
||||
- name: Unraid Forum
|
||||
url: https://forums.unraid.net/topic/118390-support-josh5-steam-headless/
|
||||
about: For Unraid users, please check the forums to see if your question has already been answered.
|
||||
50
.github/label-actions.yml
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
---
|
||||
|
||||
# Configuration for Label Actions - https://github.com/dessant/label-actions
|
||||
|
||||
added:
|
||||
comment: >
|
||||
This feature has been added and will be available in the next release.
|
||||
This issue will be automatically closed once the update is available.
|
||||
|
||||
fixed:
|
||||
comment: >
|
||||
This bug has been fixed and will be available in the next release.
|
||||
This issue will be automatically closed once the update is available.
|
||||
|
||||
invalid:duplicate:
|
||||
comment: >
|
||||
:wave: @{issue-author}, this appears to be a duplicate of a pre-existing issue.
|
||||
close: true
|
||||
lock: true
|
||||
unlabel: 'status:awaiting-triage'
|
||||
|
||||
-invalid:duplicate:
|
||||
reopen: true
|
||||
unlock: true
|
||||
|
||||
invalid:support:
|
||||
comment: >
|
||||
:wave: @{issue-author}, we use the issue tracker exclusively for bug reports.
|
||||
However, this issue appears to be a support request. Please use our
|
||||
[Discord Server](https://unmanic.app/discord) to get help. Thanks.
|
||||
close: true
|
||||
lock: true
|
||||
lock-reason: 'off-topic'
|
||||
unlabel: 'status:awaiting-triage'
|
||||
|
||||
-invalid:support:
|
||||
reopen: true
|
||||
unlock: true
|
||||
|
||||
invalid:template-incomplete:
|
||||
issues:
|
||||
comment: >
|
||||
:wave: @{issue-author}, please edit your issue to complete the template with
|
||||
all the required info. Your issue will be automatically closed in 5 days if
|
||||
the template is not completed. Thanks.
|
||||
prs:
|
||||
comment: >
|
||||
:wave: @{issue-author}, please edit your PR to complete the template with
|
||||
all the required info. Your PR will be automatically closed in 5 days if
|
||||
the template is not completed. Thanks.
|
||||
54
.github/workflows/build_ci.yml
vendored
@@ -1,3 +1,5 @@
|
||||
---
|
||||
|
||||
name: Build and Deploy CI
|
||||
|
||||
on:
|
||||
@@ -6,6 +8,9 @@ on:
|
||||
tags: [ '**' ]
|
||||
pull_request:
|
||||
branches: [ staging, master ]
|
||||
schedule:
|
||||
# At 02:30 on Saturday
|
||||
- cron: '30 2 * * 6'
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -13,6 +18,10 @@ jobs:
|
||||
|
||||
name: Build Docker Image
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
flavour: ["debian", "arch"]
|
||||
|
||||
steps:
|
||||
# Fetch shallow git repository
|
||||
@@ -38,26 +47,35 @@ jobs:
|
||||
if: success()
|
||||
id: prepare
|
||||
run: |
|
||||
echo "GITHUB_REF:${GITHUB_REF}"
|
||||
echo "GITHUB_REPOSITORY:${GITHUB_REPOSITORY}"
|
||||
FLAVOUR=${{ matrix.flavour }}
|
||||
echo "FLAVOUR='${FLAVOUR}'"
|
||||
echo "GITHUB_REF='${GITHUB_REF}'"
|
||||
echo "GITHUB_REPOSITORY='${GITHUB_REPOSITORY}'"
|
||||
DOCKER_IMAGE=docker.io/josh5/steam-headless
|
||||
VERSION_TAG=${GITHUB_REF#refs/*/}
|
||||
|
||||
DOCKER_TAGS=""
|
||||
if [[ ${VERSION_TAG%/merge} == 'master' ]]; then
|
||||
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:latest,"
|
||||
if [[ ${FLAVOUR} == 'debian' ]]; then
|
||||
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:latest,"
|
||||
fi
|
||||
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:${FLAVOUR},"
|
||||
elif [[ ${VERSION_TAG%/merge} == 'staging' ]]; then
|
||||
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:staging,"
|
||||
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:${FLAVOUR}-staging,"
|
||||
elif [[ ${VERSION_TAG%/merge} =~ "dev-"* ]]; then
|
||||
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:${VERSION_TAG%/merge},"
|
||||
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:${FLAVOUR}-${VERSION_TAG%/merge},"
|
||||
fi
|
||||
if [[ ${GITHUB_REF} == refs/tags/* ]]; then
|
||||
VERSION=${GITHUB_REF#refs/tags/}
|
||||
if [[ ${VERSION} =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}[-\w]*$ ]]; then
|
||||
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:${VERSION},"
|
||||
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:latest,"
|
||||
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:${FLAVOUR}-${VERSION},"
|
||||
if [[ ${FLAVOUR} == 'debian' ]]; then
|
||||
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:latest,"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
echo "DOCKER_TAGS='${DOCKER_TAGS}'"
|
||||
|
||||
echo "Build: [$(date +"%F %T")] [${GITHUB_REF_NAME}] [${GITHUB_SHA}] [${FLAVOUR}]" > ./overlay/version.txt
|
||||
|
||||
DOCKER_PUSH="true"
|
||||
if [[ ${DOCKER_IMAGE} != 'docker.io/josh5/steam-headless' ]]; then
|
||||
@@ -69,11 +87,16 @@ jobs:
|
||||
if [[ ${VERSION_TAG%/merge} =~ ^[0-9]+$ ]]; then
|
||||
DOCKER_PUSH="false"
|
||||
fi
|
||||
if [[ "X${DOCKER_TAGS}" == "X" ]]; then
|
||||
DOCKER_PUSH="false"
|
||||
fi
|
||||
echo "DOCKER_PUSH='${DOCKER_PUSH}'"
|
||||
cat ./overlay/version.txt
|
||||
|
||||
echo ::set-output name=docker_image::${DOCKER_IMAGE}
|
||||
echo ::set-output name=docker_tags::$(echo ${DOCKER_TAGS} | sed 's/,$//')
|
||||
echo ::set-output name=docker_platforms::linux/amd64
|
||||
echo ::set-output name=docker_push::${DOCKER_PUSH}
|
||||
echo "docker_image=${DOCKER_IMAGE}" >> $GITHUB_OUTPUT
|
||||
echo "docker_tags=$(echo ${DOCKER_TAGS} | sed 's/,$//')" >> $GITHUB_OUTPUT
|
||||
echo "docker_platforms=linux/amd64" >> $GITHUB_OUTPUT
|
||||
echo "docker_push=${DOCKER_PUSH}" >> $GITHUB_OUTPUT
|
||||
|
||||
# Cache the build
|
||||
- name: Cache Docker layers
|
||||
@@ -81,9 +104,9 @@ jobs:
|
||||
id: cache
|
||||
with:
|
||||
path: /tmp/.buildx-cache
|
||||
key: ${{ runner.os }}-buildx-${{ github.sha }}
|
||||
key: ${{ runner.os }}-buildx-${{ matrix.flavour }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-buildx-
|
||||
${{ runner.os }}-buildx-${{ matrix.flavour }}-
|
||||
|
||||
# Login to Docker Hub
|
||||
- name: Login to Docker Hub
|
||||
@@ -99,7 +122,8 @@ jobs:
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
file: Dockerfile
|
||||
file: Dockerfile.${{ matrix.flavour }}
|
||||
pull: true
|
||||
platforms: ${{ steps.prepare.outputs.docker_platforms }}
|
||||
push: ${{ steps.prepare.outputs.docker_push }}
|
||||
tags: |
|
||||
|
||||
51
.github/workflows/issues-stale.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
---
|
||||
|
||||
name: Stale Issues / PRs
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '00 00 * * *'
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
name: Check Stale Issues / PRs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Stale
|
||||
uses: actions/stale@v5
|
||||
with:
|
||||
close-issue-message: >
|
||||
This issue was closed because it has been stalled for 5 days with no activity.
|
||||
close-pr-message: >
|
||||
This PR was closed because it has been stalled for 10 days with no activity.
|
||||
days-before-stale: 60
|
||||
days-before-close: 10
|
||||
exempt-all-assignees: true
|
||||
exempt-issue-labels: 'added,fixed,type:enhancement,status:awaiting-triage,status:in-progress'
|
||||
exempt-pr-labels: 'type:dependencies,status:in-progress,status:in-review'
|
||||
stale-issue-label: 'stale'
|
||||
stale-issue-message: >
|
||||
This issue is stale because it has been open for 30 days with no activity.
|
||||
Comment or remove the stale label, otherwise this will be closed in 5 days.
|
||||
stale-pr-label: 'stale'
|
||||
stale-pr-message: >
|
||||
This PR is stale because it has been open for 60 days with no activity.
|
||||
Comment or remove the stale label, otherwise this will be closed in 10 days.
|
||||
|
||||
- name: Invalid Template
|
||||
uses: actions/stale@v5
|
||||
with:
|
||||
close-issue-message: >
|
||||
This issue was closed because the the template was not completed after 5 days.
|
||||
close-pr-message: >
|
||||
This PR was closed because the the template was not completed after 5 days.
|
||||
days-before-stale: 0
|
||||
days-before-close: 5
|
||||
exempt-pr-labels: 'type:dependencies,status:in-progress,status:in-review'
|
||||
only-labels: 'invalid:template-incomplete'
|
||||
stale-issue-label: 'invalid:template-incomplete'
|
||||
stale-issue-message: >
|
||||
Invalid issues template.
|
||||
stale-pr-label: 'invalid:template-incomplete'
|
||||
stale-pr-message: >
|
||||
Invalid PR template.
|
||||
17
.github/workflows/issues.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
|
||||
name: Issues
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [labeled, unlabeled]
|
||||
|
||||
jobs:
|
||||
label:
|
||||
name: Label Issues
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Label Issues
|
||||
uses: dessant/label-actions@v2
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
363
Dockerfile
@@ -1,363 +0,0 @@
|
||||
FROM debian:bullseye-slim
|
||||
|
||||
# Update package repos
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& sed -i '/^.*main/ s/$/ contrib non-free/' /etc/apt/sources.list \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Update locale
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
&& \
|
||||
echo "**** Install and configure locals ****" \
|
||||
&& apt-get -y install --no-install-recommends \
|
||||
locales \
|
||||
procps \
|
||||
&& echo 'en_US.UTF-8 UTF-8' > /etc/locale.gen \
|
||||
&& locale-gen \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& apt-get clean autoclean -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/tmp/* \
|
||||
/tmp/* \
|
||||
&& \
|
||||
echo
|
||||
ENV \
|
||||
LANG=en_US.UTF-8 \
|
||||
LANGUAGE=en_US:en \
|
||||
LC_ALL=en_US.UTF-8
|
||||
|
||||
# Re-install certificates
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
&& \
|
||||
echo "**** Install certificates ****" \
|
||||
&& apt-get -y install --reinstall \
|
||||
ca-certificates \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& apt-get clean autoclean -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/tmp/* \
|
||||
/tmp/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install core packages
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
&& \
|
||||
echo "**** Install tools ****" \
|
||||
&& apt-get -y install \
|
||||
bash \
|
||||
bash-completion \
|
||||
gcc \
|
||||
git \
|
||||
kmod \
|
||||
less \
|
||||
make \
|
||||
nano \
|
||||
sudo \
|
||||
vim \
|
||||
wget \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& apt-get clean autoclean -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/tmp/* \
|
||||
/tmp/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install desktop requirements
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
&& \
|
||||
echo "**** Install desktop requirements ****" \
|
||||
&& apt-get -y install --no-install-recommends \
|
||||
dbus-x11 \
|
||||
libxcomposite-dev \
|
||||
libxcursor1 \
|
||||
man-db \
|
||||
mlocate \
|
||||
net-tools \
|
||||
pciutils \
|
||||
pkg-config \
|
||||
python3 \
|
||||
python3-numpy \
|
||||
python3-setuptools \
|
||||
rsync \
|
||||
x11vnc \
|
||||
xauth \
|
||||
xorg \
|
||||
xserver-xorg-legacy \
|
||||
xvfb \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& apt-get clean autoclean -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/tmp/* \
|
||||
/tmp/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install supervisor
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
&& \
|
||||
echo "**** Install supervisor ****" \
|
||||
&& apt-get -y install \
|
||||
supervisor \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& apt-get clean autoclean -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/tmp/* \
|
||||
/tmp/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install openssh server
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
&& \
|
||||
echo "**** Install openssh server ****" \
|
||||
&& apt-get -y install \
|
||||
openssh-server \
|
||||
&& echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& apt-get clean autoclean -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/tmp/* \
|
||||
/tmp/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install noVNC
|
||||
ARG NOVNC_VERSION=1.2.0
|
||||
RUN \
|
||||
echo "**** Fetch noVNC ****" \
|
||||
&& cd /tmp \
|
||||
&& wget -O /tmp/novnc.tar.gz https://github.com/novnc/noVNC/archive/v${NOVNC_VERSION}.tar.gz \
|
||||
&& \
|
||||
echo "**** Extract noVNC ****" \
|
||||
&& cd /tmp \
|
||||
&& tar -xvf /tmp/novnc.tar.gz \
|
||||
&& \
|
||||
echo "**** Configure noVNC ****" \
|
||||
&& cd /tmp/noVNC-${NOVNC_VERSION} \
|
||||
&& sed -i 's/credentials: { password: password } });/credentials: { password: password },\n wsProtocols: ["'"binary"'"] });/g' app/ui.js \
|
||||
&& mkdir -p /opt \
|
||||
&& rm -rf /opt/noVNC \
|
||||
&& cd /opt \
|
||||
&& mv -f /tmp/noVNC-${NOVNC_VERSION} /opt/noVNC \
|
||||
&& cd /opt/noVNC \
|
||||
&& ln -s vnc.html index.html \
|
||||
&& chmod -R 755 /opt/noVNC \
|
||||
&& \
|
||||
echo "**** Modify noVNC title ****" \
|
||||
&& sed -i '/ document.title =/c\ document.title = "Steam Headless - noVNC";' \
|
||||
/opt/noVNC/app/ui.js \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& rm -rf \
|
||||
/tmp/noVNC* \
|
||||
/tmp/novnc.tar.gz
|
||||
|
||||
# Install Websockify
|
||||
ARG WEBSOCKETIFY_VERSION=0.10.0
|
||||
RUN \
|
||||
echo "**** Fetch Websockify ****" \
|
||||
&& cd /tmp \
|
||||
&& wget -O /tmp/websockify.tar.gz https://github.com/novnc/websockify/archive/v${WEBSOCKETIFY_VERSION}.tar.gz \
|
||||
&& \
|
||||
echo "**** Extract Websockify ****" \
|
||||
&& cd /tmp \
|
||||
&& tar -xvf /tmp/websockify.tar.gz \
|
||||
&& \
|
||||
echo "**** Install Websockify to main ****" \
|
||||
&& cd /tmp/websockify-${WEBSOCKETIFY_VERSION} \
|
||||
&& python3 ./setup.py install \
|
||||
&& \
|
||||
echo "**** Install Websockify to noVNC path ****" \
|
||||
&& cd /tmp \
|
||||
&& mv -v /tmp/websockify-${WEBSOCKETIFY_VERSION} /opt/noVNC/utils/websockify \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& rm -rf \
|
||||
/tmp/websockify-* \
|
||||
/tmp/websockify.tar.gz
|
||||
|
||||
# Install desktop environment
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
&& \
|
||||
echo "**** Install desktop environment ****" \
|
||||
&& apt-get -y install \
|
||||
xfce4 \
|
||||
xfce4-terminal \
|
||||
msttcorefonts \
|
||||
fonts-vlgothic \
|
||||
gedit \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& apt-get clean autoclean -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/tmp/* \
|
||||
/tmp/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install firefox
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
&& \
|
||||
echo "**** Install firefox ****" \
|
||||
&& apt-get -y install \
|
||||
firefox-esr \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& apt-get clean autoclean -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/tmp/* \
|
||||
/tmp/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install Steam
|
||||
RUN \
|
||||
echo "**** Install steam ****" \
|
||||
&& dpkg --add-architecture i386 \
|
||||
&& apt-get update \
|
||||
&& echo steam steam/question select "I AGREE" | debconf-set-selections \
|
||||
&& echo steam steam/license note '' | debconf-set-selections \
|
||||
&& apt-get -y install \
|
||||
steam \
|
||||
steam-devices \
|
||||
vulkan-tools \
|
||||
mesa-utils \
|
||||
mesa-vulkan-drivers \
|
||||
libglx-mesa0:i386 \
|
||||
mesa-vulkan-drivers:i386 \
|
||||
libgl1-mesa-dri:i386 \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& apt-get clean autoclean -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/tmp/* \
|
||||
/tmp/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Setup browser audio streaming deps
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
&& \
|
||||
echo "**** Install audio streaming deps ****" \
|
||||
&& apt-get -y install --no-install-recommends \
|
||||
bzip2 \
|
||||
gstreamer1.0-alsa \
|
||||
gstreamer1.0-gl \
|
||||
gstreamer1.0-gtk3 \
|
||||
gstreamer1.0-libav \
|
||||
gstreamer1.0-plugins-base \
|
||||
gstreamer1.0-plugins-good \
|
||||
gstreamer1.0-pulseaudio \
|
||||
gstreamer1.0-qt5 \
|
||||
gstreamer1.0-tools \
|
||||
gstreamer1.0-x \
|
||||
libglu1-mesa \
|
||||
libgstreamer1.0-0 \
|
||||
libgtk2.0-0 \
|
||||
libncursesw5 \
|
||||
libopenal1 \
|
||||
libsdl-image1.2 \
|
||||
libsdl-ttf2.0-0 \
|
||||
libsdl1.2debian \
|
||||
libsndfile1 \
|
||||
novnc \
|
||||
pulseaudio \
|
||||
ucspi-tcp \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& apt-get clean autoclean -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/tmp/* \
|
||||
/tmp/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Configure default user and set env
|
||||
ENV \
|
||||
USER="default" \
|
||||
USER_PASSWORD="password" \
|
||||
USER_HOME="/home/default" \
|
||||
TZ="Pacific/Auckland" \
|
||||
USER_LOCALES="en_US.UTF-8 UTF-8"
|
||||
RUN \
|
||||
echo "**** Configure default user '${USER}' ****" \
|
||||
&& mkdir -p \
|
||||
${USER_HOME} \
|
||||
/games \
|
||||
&& useradd -d ${USER_HOME} -s /bin/bash ${USER} \
|
||||
&& chown -R ${USER} \
|
||||
${USER_HOME} \
|
||||
/games \
|
||||
&& echo "${USER} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
|
||||
|
||||
# Add FS overlay
|
||||
COPY overlay /
|
||||
|
||||
# Set display environment variables
|
||||
ENV \
|
||||
DISPLAY_CDEPTH="24" \
|
||||
DISPLAY_DPI="96" \
|
||||
DISPLAY_REFRESH="60" \
|
||||
DISPLAY_SIZEH="900" \
|
||||
DISPLAY_SIZEW="1600" \
|
||||
DISPLAY_VIDEO_PORT="DFP" \
|
||||
DISPLAY=":0" \
|
||||
NVIDIA_DRIVER_CAPABILITIES="all" \
|
||||
NVIDIA_VISIBLE_DEVICES="all"
|
||||
|
||||
# Be sure that the noVNC port is exposed
|
||||
EXPOSE 8083
|
||||
EXPOSE 32123
|
||||
|
||||
# Set entrypoint
|
||||
RUN chmod +x /entrypoint.sh
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
450
Dockerfile.arch
Normal file
@@ -0,0 +1,450 @@
|
||||
# Steam Headless (Arch Linux)
|
||||
# (WIP) An Arch variant of the steam-headless image
|
||||
# It is curerently my intent to switch to arch as the main
|
||||
# image base once SteamOS 3 is released (pending review)
|
||||
#
|
||||
FROM archlinux:latest
|
||||
LABEL maintainer="Josh.5 <jsunnex@gmail.com>"
|
||||
|
||||
# Update package repos
|
||||
RUN \
|
||||
echo "**** Update package manager ****" \
|
||||
&& sed -i 's/^NoProgressBar/#NoProgressBar/g' /etc/pacman.conf \
|
||||
&& echo -e "[multilib]\nInclude = /etc/pacman.d/mirrorlist" >> /etc/pacman.conf \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Update locale
|
||||
RUN \
|
||||
echo "**** Configure locals ****" \
|
||||
&& echo 'en_US.UTF-8 UTF-8' > /etc/locale.gen \
|
||||
&& locale-gen \
|
||||
&& \
|
||||
echo
|
||||
ENV \
|
||||
LANG=en_US.UTF-8 \
|
||||
LANGUAGE=en_US:en \
|
||||
LC_ALL=en_US.UTF-8
|
||||
|
||||
# Re-install certificates
|
||||
RUN \
|
||||
echo "**** Install certificates ****" \
|
||||
&& pacman -Syu --noconfirm --needed \
|
||||
ca-certificates \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& pacman -Scc --noconfirm \
|
||||
&& rm -fr /var/lib/pacman/sync/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install core packages
|
||||
RUN \
|
||||
echo "**** Install tools ****" \
|
||||
&& pacman -Syu --noconfirm --needed \
|
||||
base-devel \
|
||||
bash \
|
||||
bash-completion \
|
||||
curl \
|
||||
docbook-xml \
|
||||
docbook-xsl \
|
||||
fakeroot \
|
||||
git \
|
||||
jq \
|
||||
less \
|
||||
locate \
|
||||
man-db \
|
||||
nano \
|
||||
net-tools \
|
||||
pciutils \
|
||||
pkg-config \
|
||||
procps \
|
||||
psmisc \
|
||||
psutils \
|
||||
rsync \
|
||||
screen \
|
||||
sudo \
|
||||
unzip \
|
||||
vim \
|
||||
wget \
|
||||
xz \
|
||||
&& \
|
||||
echo "**** Install python ****" \
|
||||
&& pacman -Syu --noconfirm --needed \
|
||||
python \
|
||||
python-numpy \
|
||||
python-pip \
|
||||
python-setuptools \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& pacman -Scc --noconfirm \
|
||||
&& rm -fr /var/lib/pacman/sync/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Configure default user and set user env
|
||||
ENV \
|
||||
PUID=99 \
|
||||
PGID=100 \
|
||||
UMASK=000 \
|
||||
USER="default" \
|
||||
USER_PASSWORD="password" \
|
||||
USER_HOME="/home/default" \
|
||||
TZ="Pacific/Auckland" \
|
||||
USER_LOCALES="en_US.UTF-8 UTF-8"
|
||||
RUN \
|
||||
echo "**** Configure default user '${USER}' ****" \
|
||||
&& mkdir -p \
|
||||
${USER_HOME} \
|
||||
&& useradd -d ${USER_HOME} -s /bin/bash ${USER} \
|
||||
&& chown -R ${USER} \
|
||||
${USER_HOME} \
|
||||
&& echo "${USER} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install yay
|
||||
RUN \
|
||||
echo "**** Install Yay ****" \
|
||||
&& pacman -Sy \
|
||||
&& su - default -c 'git clone https://aur.archlinux.org/yay.git /tmp/yay && cd /tmp/yay && makepkg --noconfirm --syncdeps --install' \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& pacman -Scc --noconfirm \
|
||||
&& rm -fr /var/lib/pacman/sync/* \
|
||||
&& rm -rf \
|
||||
/tmp/yay* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install supervisor
|
||||
RUN \
|
||||
echo "**** Install supervisor ****" \
|
||||
&& pacman -Syu --noconfirm --needed \
|
||||
supervisor \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& pacman -Scc --noconfirm \
|
||||
&& rm -fr /var/lib/pacman/sync/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# XFS requirements
|
||||
RUN \
|
||||
echo "**** Install XFS requirements ****" \
|
||||
&& pacman -Syu --noconfirm --needed \
|
||||
xfsdump \
|
||||
xfsprogs \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& pacman -Scc --noconfirm \
|
||||
&& rm -fr /var/lib/pacman/sync/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install mesa requirements
|
||||
RUN \
|
||||
echo "**** Install mesa and vulkan requirements ****" \
|
||||
&& pacman -Syu --noconfirm --needed \
|
||||
glu \
|
||||
libva-mesa-driver \
|
||||
mesa-utils \
|
||||
mesa-vdpau \
|
||||
pciutils \
|
||||
vulkan-mesa-layers \
|
||||
vdpauinfo \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& pacman -Scc --noconfirm \
|
||||
&& rm -fr /var/lib/pacman/sync/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install X Server requirements
|
||||
ENV \
|
||||
XORG_SOCKET_DIR="/tmp/.X11-unix" \
|
||||
XDG_RUNTIME_DIR="/tmp/.X11-unix/run"
|
||||
RUN \
|
||||
echo "**** Install X Server requirements ****" \
|
||||
&& pacman -Syu --noconfirm --needed \
|
||||
avahi \
|
||||
dbus \
|
||||
lib32-fontconfig \
|
||||
ttf-liberation \
|
||||
x11vnc \
|
||||
xorg \
|
||||
xorg-apps \
|
||||
xorg-font-util \
|
||||
xorg-fonts-misc \
|
||||
xorg-fonts-type1 \
|
||||
xorg-server \
|
||||
xorg-server-xephyr \
|
||||
xorg-server-xvfb \
|
||||
xorg-xauth \
|
||||
xorg-xbacklight \
|
||||
xorg-xhost \
|
||||
xorg-xinit \
|
||||
xorg-xinput \
|
||||
xorg-xkill \
|
||||
xorg-xprop \
|
||||
xorg-xrandr \
|
||||
xorg-xsetroot \
|
||||
xorg-xwininfo \
|
||||
xterm \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& pacman -Scc --noconfirm \
|
||||
&& rm -fr /var/lib/pacman/sync/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install audio requirements
|
||||
ENV \
|
||||
PULSE_SOCKET_DIR="/tmp/pulse" \
|
||||
PULSE_SERVER="unix:/tmp/pulse/pulse-socket"
|
||||
RUN \
|
||||
echo "**** Install X Server requirements ****" \
|
||||
&& pacman -Syu --noconfirm --needed \
|
||||
alsa-utils \
|
||||
pavucontrol \
|
||||
pulseaudio \
|
||||
pulseaudio-alsa \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& pacman -Scc --noconfirm \
|
||||
&& rm -fr /var/lib/pacman/sync/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install desktop environment
|
||||
# TODO: Install equivelent of 'msttcorefonts' and 'fonts-vlgothic'
|
||||
RUN \
|
||||
echo "**** Install desktop environment ****" \
|
||||
&& pacman -Syu --noconfirm --needed \
|
||||
gedit \
|
||||
xfce4 \
|
||||
xfce4-goodies \
|
||||
xfce4-terminal \
|
||||
ttf-liberation \
|
||||
# Delete these as they are not needed at all
|
||||
&& rm -f \
|
||||
/usr/share/applications/software-properties-drivers.desktop \
|
||||
/usr/share/applications/xfce4-about.desktop \
|
||||
/usr/share/applications/xfce4-session-logout.desktop \
|
||||
# Hide these apps. They can be displayed if a user really wants them.
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/xfce4-accessibility-settings.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/xfce4-color-settings.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/xfce4-mail-reader.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/vim.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/thunar-settings.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/thunar.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/pavucontrol.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/x11vnc.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/xterm.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/uxterm.desktop \
|
||||
# Force these apps to be "System" Apps rather than "Categories=System;Utility;Core;GTK;Filesystem;"
|
||||
&& sed -i 's/^Categories=.*$/Categories=System;/' /usr/share/applications/xfce4-appfinder.desktop \
|
||||
&& sed -i 's/^Categories=.*$/Categories=System;/' /usr/share/applications/thunar-bulk-rename.desktop \
|
||||
&& sed -i 's/^Categories=.*$/Categories=System;/' /usr/share/applications/org.gnome.gedit.desktop \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& pacman -Scc --noconfirm \
|
||||
&& rm -fr /var/lib/pacman/sync/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# TODO: Add support for flatpaks
|
||||
# Note: Debian Bullseye had bubblewrap v0.4.1 which worked fine in the Nvidia docker runtime
|
||||
# At the moment this is only working beacuse /proc is being mounted again in 10-setup_user.sh
|
||||
# Need to find a better solution for this...
|
||||
ARG BUBBLEWRAP_VERSION=0.8.0
|
||||
ENV \
|
||||
XDG_DATA_DIRS="/home/default/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share/:/usr/share/"
|
||||
RUN \
|
||||
echo "**** Install flatpak support ****" \
|
||||
&& pacman -Syu --noconfirm --needed \
|
||||
flatpak \
|
||||
gnome-software \
|
||||
xdg-desktop-portal-gtk \
|
||||
&& \
|
||||
#echo "**** Build and install custom bubblewrap ****" \
|
||||
# && cd /tmp \
|
||||
# && wget -O /tmp/bubblewrap-${BUBBLEWRAP_VERSION:?}.tar.xz https://github.com/containers/bubblewrap/releases/download/v${BUBBLEWRAP_VERSION:?}/bubblewrap-${BUBBLEWRAP_VERSION:?}.tar.xz \
|
||||
# && tar -xvf /tmp/bubblewrap-${BUBBLEWRAP_VERSION:?}.tar.xz \
|
||||
# && cd /tmp/bubblewrap-${BUBBLEWRAP_VERSION:?} \
|
||||
# && sed -i 's|die ("Unexpected capabilities but not setuid, old file caps config?");|printf ("Unexpected capabilities but not setuid, old file caps config?");|' ./bubblewrap.c \
|
||||
# && ./autogen.sh \
|
||||
# && make clean \
|
||||
# && make \
|
||||
# && make install
|
||||
#&& \
|
||||
echo "**** Configure flatpak ****" \
|
||||
&& chmod u-s /usr/bin/bwrap \
|
||||
&& flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& pacman -Scc --noconfirm \
|
||||
&& rm -fr /var/lib/pacman/sync/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install noVNC
|
||||
# TODO: Add nginx or remove the whole proxy setup and just connect directly for audio (I think that is the better option)
|
||||
ARG NOVNC_VERSION=1.2.0
|
||||
RUN \
|
||||
echo "**** Fetch noVNC ****" \
|
||||
&& cd /tmp \
|
||||
&& wget -O /tmp/novnc.tar.gz https://github.com/novnc/noVNC/archive/v${NOVNC_VERSION}.tar.gz \
|
||||
&& \
|
||||
echo "**** Extract noVNC ****" \
|
||||
&& cd /tmp \
|
||||
&& tar -xvf /tmp/novnc.tar.gz \
|
||||
&& \
|
||||
echo "**** Configure noVNC ****" \
|
||||
&& cd /tmp/noVNC-${NOVNC_VERSION} \
|
||||
&& sed -i 's/credentials: { password: password } });/credentials: { password: password },\n wsProtocols: ["'"binary"'"] });/g' app/ui.js \
|
||||
&& mkdir -p /opt \
|
||||
&& rm -rf /opt/noVNC \
|
||||
&& cd /opt \
|
||||
&& mv -f /tmp/noVNC-${NOVNC_VERSION} /opt/noVNC \
|
||||
&& cd /opt/noVNC \
|
||||
&& ln -s vnc.html index.html \
|
||||
&& chmod -R 755 /opt/noVNC \
|
||||
&& \
|
||||
echo "**** Modify noVNC title ****" \
|
||||
&& sed -i '/ document.title =/c\ document.title = "Steam Headless - noVNC";' \
|
||||
/opt/noVNC/app/ui.js \
|
||||
&& \
|
||||
echo "**** Install nginx support ****" \
|
||||
&& pacman -Syu --noconfirm --needed \
|
||||
nginx \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& pacman -Scc --noconfirm \
|
||||
&& rm -fr /var/lib/pacman/sync/* \
|
||||
&& rm -rf \
|
||||
/tmp/noVNC* \
|
||||
/tmp/novnc.tar.gz \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install Websockify
|
||||
ARG WEBSOCKETIFY_VERSION=0.10.0
|
||||
RUN \
|
||||
echo "**** Fetch Websockify ****" \
|
||||
&& cd /tmp \
|
||||
&& wget -O /tmp/websockify.tar.gz https://github.com/novnc/websockify/archive/v${WEBSOCKETIFY_VERSION}.tar.gz \
|
||||
&& \
|
||||
echo "**** Extract Websockify ****" \
|
||||
&& cd /tmp \
|
||||
&& tar -xvf /tmp/websockify.tar.gz \
|
||||
&& \
|
||||
echo "**** Install Websockify to main ****" \
|
||||
&& cd /tmp/websockify-${WEBSOCKETIFY_VERSION} \
|
||||
&& python3 ./setup.py install \
|
||||
&& \
|
||||
echo "**** Install Websockify to noVNC path ****" \
|
||||
&& cd /tmp \
|
||||
&& mv -v /tmp/websockify-${WEBSOCKETIFY_VERSION} /opt/noVNC/utils/websockify \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& rm -rf \
|
||||
/tmp/websockify-* \
|
||||
/tmp/websockify.tar.gz \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Setup browser audio streaming deps
|
||||
RUN \
|
||||
echo "**** Install audio streaming deps ****" \
|
||||
&& pacman -Syu --noconfirm --needed \
|
||||
bzip2 \
|
||||
gst-libav \
|
||||
gst-plugins-bad \
|
||||
gst-plugins-base \
|
||||
gst-plugins-good \
|
||||
gst-plugins-ugly \
|
||||
&& \
|
||||
echo "**** Fetch ucspi-tcp ****" \
|
||||
&& mkdir -p /tmp/ucspi-tcp-0.88 \
|
||||
&& cd /tmp \
|
||||
#&& wget -O /tmp/ucspi-tcp.tar.gz https://github.com/trafficgate/ucspi-tcp/archive/refs/heads/master.tar.gz \
|
||||
&& wget -O /tmp/ucspi-tcp.tar.gz http://cr.yp.to/ucspi-tcp/ucspi-tcp-0.88.tar.gz \
|
||||
&& cd /tmp/ucspi-tcp-0.88 \
|
||||
&& tar -xvf /tmp/ucspi-tcp.tar.gz --strip-components=1 \
|
||||
&& \
|
||||
echo "**** Build and install ucspi-tcp ****" \
|
||||
&& wget -O /tmp/ucspi-tcp-0.88/ucspi-tcp-0.88.errno.patch https://git.alpinelinux.org/aports/plain/testing/ucspi-tcp/ucspi-tcp-0.88.errno.patch \
|
||||
&& wget -O /tmp/ucspi-tcp-0.88/ucspi-tcp-0.88.a_record.patch https://git.alpinelinux.org/aports/plain/testing/ucspi-tcp/ucspi-tcp-0.88.a_record.patch \
|
||||
&& patch -p1 --input=ucspi-tcp-0.88.errno.patch \
|
||||
&& patch -p1 --input=ucspi-tcp-0.88.a_record.patch \
|
||||
&& sed -i 's|^/usr/local|/usr|' /tmp/ucspi-tcp-0.88/conf-home \
|
||||
&& make \
|
||||
&& for f in tcpserver tcprules tcprulescheck argv0 recordio tcpclient *\@ tcpcat mconnect mconnect-io addcr delcr fixcrio rblsmtpd; do \
|
||||
cp $f /usr/bin/$f; \
|
||||
done \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& pacman -Scc --noconfirm \
|
||||
&& rm -fr /var/lib/pacman/sync/* \
|
||||
&& rm -rf \
|
||||
/tmp/ucspi-tcp-* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install Steam
|
||||
RUN \
|
||||
echo "**** Install X Server requirements ****" \
|
||||
&& pacman -Syu --noconfirm --needed \
|
||||
steam \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& pacman -Scc --noconfirm \
|
||||
&& rm -fr /var/lib/pacman/sync/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Add FS overlay
|
||||
COPY overlay /
|
||||
|
||||
RUN \
|
||||
echo "**** Setup Steam Supervisor ****" \
|
||||
&& sed -i 's#/usr/games/steam#/usr/bin/steam#g' /etc/supervisor.d/steam.ini \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Set display environment variables
|
||||
ENV \
|
||||
DISPLAY_CDEPTH="24" \
|
||||
DISPLAY_REFRESH="120" \
|
||||
DISPLAY_SIZEH="900" \
|
||||
DISPLAY_SIZEW="1600" \
|
||||
DISPLAY_VIDEO_PORT="DFP" \
|
||||
DISPLAY=":55"
|
||||
ENV \
|
||||
NVIDIA_DRIVER_CAPABILITIES="all" \
|
||||
NVIDIA_VISIBLE_DEVICES="all"
|
||||
|
||||
# Set container configuration environment variables
|
||||
ENV \
|
||||
MODE="primary" \
|
||||
WEB_UI_MODE="vnc" \
|
||||
ENABLE_VNC_AUDIO="true" \
|
||||
NEKO_PASSWORD=neko \
|
||||
NEKO_PASSWORD_ADMIN=admin \
|
||||
ENABLE_STEAM="true" \
|
||||
STEAM_ARGS="-silent" \
|
||||
ENABLE_SUNSHINE="false" \
|
||||
ENABLE_EVDEV_INPUTS="false"
|
||||
|
||||
# Configure required ports
|
||||
ENV \
|
||||
PORT_NOVNC_WEB="8083" \
|
||||
NEKO_NAT1TO1=""
|
||||
|
||||
# Expose the required ports
|
||||
EXPOSE 8083
|
||||
|
||||
# Set entrypoint
|
||||
RUN chmod +x /entrypoint.sh
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
582
Dockerfile.debian
Normal file
@@ -0,0 +1,582 @@
|
||||
FROM debian:bookworm-slim
|
||||
LABEL maintainer="Josh.5 <jsunnex@gmail.com>"
|
||||
|
||||
# Update package repos
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& sed -i '/^Components: main/ s/$/ contrib non-free/' /etc/apt/sources.list.d/debian.sources \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Update locale
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
&& \
|
||||
echo "**** Install and configure locals ****" \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
locales \
|
||||
&& echo 'en_US.UTF-8 UTF-8' > /etc/locale.gen \
|
||||
&& locale-gen \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& apt-get clean autoclean -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/tmp/* \
|
||||
/tmp/* \
|
||||
&& \
|
||||
echo
|
||||
ENV \
|
||||
LANG=en_US.UTF-8 \
|
||||
LANGUAGE=en_US:en \
|
||||
LC_ALL=en_US.UTF-8
|
||||
|
||||
# Re-install certificates
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
&& \
|
||||
echo "**** Install certificates ****" \
|
||||
&& apt-get install -y --reinstall \
|
||||
ca-certificates \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& apt-get clean autoclean -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/tmp/* \
|
||||
/tmp/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install core packages
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
&& \
|
||||
echo "**** Install tools ****" \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
bash \
|
||||
bash-completion \
|
||||
curl \
|
||||
git \
|
||||
jq \
|
||||
less \
|
||||
man-db \
|
||||
mlocate \
|
||||
nano \
|
||||
net-tools \
|
||||
p7zip-full \
|
||||
patch \
|
||||
pciutils \
|
||||
pkg-config \
|
||||
procps \
|
||||
psmisc \
|
||||
psutils \
|
||||
rsync \
|
||||
screen \
|
||||
sudo \
|
||||
unzip \
|
||||
vim \
|
||||
wget \
|
||||
xmlstarlet \
|
||||
xz-utils \
|
||||
&& \
|
||||
echo "**** Install python ****" \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
python3 \
|
||||
python3-numpy \
|
||||
python3-pip \
|
||||
python3-setuptools \
|
||||
python3-venv \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& apt-get clean autoclean -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/tmp/* \
|
||||
/tmp/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Configure default user and set user env
|
||||
ENV \
|
||||
PUID=99 \
|
||||
PGID=100 \
|
||||
UMASK=000 \
|
||||
USER="default" \
|
||||
USER_PASSWORD="password" \
|
||||
USER_HOME="/home/default" \
|
||||
TZ="Pacific/Auckland" \
|
||||
USER_LOCALES="en_US.UTF-8 UTF-8"
|
||||
RUN \
|
||||
echo "**** Configure default user '${USER}' ****" \
|
||||
&& mkdir -p \
|
||||
${USER_HOME} \
|
||||
&& useradd -d ${USER_HOME} -s /bin/bash ${USER} \
|
||||
&& chown -R ${USER} \
|
||||
${USER_HOME} \
|
||||
&& echo "${USER} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install supervisor
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
&& \
|
||||
echo "**** Install supervisor ****" \
|
||||
&& apt-get install -y \
|
||||
supervisor \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& apt-get clean autoclean -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/tmp/* \
|
||||
/tmp/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install mesa and vulkan requirements
|
||||
# TODO: Strip this section back to only what is required for all GPU types.
|
||||
# Anything only required for Intel/AMD/NVIDIA should go in the container init.
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& dpkg --add-architecture i386 \
|
||||
&& apt-get update \
|
||||
&& \
|
||||
echo "**** Install mesa requirements ****" \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
libgl1-mesa-dri \
|
||||
libgl1-mesa-glx \
|
||||
libgles2-mesa \
|
||||
libglu1-mesa \
|
||||
mesa-utils \
|
||||
mesa-utils-extra \
|
||||
&& \
|
||||
echo "**** Install vulkan requirements ****" \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
libvulkan1 \
|
||||
libvulkan1:i386 \
|
||||
mesa-vulkan-drivers \
|
||||
mesa-vulkan-drivers:i386 \
|
||||
vulkan-tools \
|
||||
&& \
|
||||
echo "**** Install desktop requirements ****" \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
libdbus-1-3 \
|
||||
libegl1 \
|
||||
libgtk-3-0 \
|
||||
libgtk2.0-0 \
|
||||
libsdl2-2.0-0 \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& apt-get clean autoclean -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/tmp/* \
|
||||
/tmp/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install X Server requirements
|
||||
# TODO: Refine this list of packages to only what is required.
|
||||
ENV \
|
||||
XORG_SOCKET_DIR="/tmp/.X11-unix" \
|
||||
XDG_RUNTIME_DIR="/tmp/.X11-unix/run" \
|
||||
XDG_SESSION_TYPE="x11"
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
&& \
|
||||
echo "**** Install X Server requirements ****" \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
avahi-utils \
|
||||
dbus-x11 \
|
||||
libxcomposite-dev \
|
||||
libxcursor1 \
|
||||
wmctrl \
|
||||
libfuse2 \
|
||||
x11-utils \
|
||||
x11-xfs-utils \
|
||||
x11-xkb-utils \
|
||||
x11-xserver-utils \
|
||||
x11vnc \
|
||||
xauth \
|
||||
xbindkeys \
|
||||
xclip \
|
||||
xcvt \
|
||||
xdotool \
|
||||
xfishtank \
|
||||
xfonts-base \
|
||||
xinit \
|
||||
xorg \
|
||||
xserver-xorg-core \
|
||||
xserver-xorg-input-evdev \
|
||||
xserver-xorg-input-libinput \
|
||||
xserver-xorg-legacy \
|
||||
xserver-xorg-video-all \
|
||||
xserver-xorg-video-dummy \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& apt-get clean autoclean -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/tmp/* \
|
||||
/tmp/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install audio requirements
|
||||
ENV \
|
||||
PULSE_SOCKET_DIR="/tmp/pulse" \
|
||||
PULSE_SERVER="unix:/tmp/pulse/pulse-socket"
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
&& \
|
||||
echo "**** Install X Server requirements ****" \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
pulseaudio \
|
||||
alsa-utils \
|
||||
libasound2 \
|
||||
libasound2-plugins \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& apt-get clean autoclean -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/tmp/* \
|
||||
/tmp/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install desktop environment
|
||||
# TODO: Specify all needed packages and add '--no-install-recommends'
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
&& \
|
||||
echo "**** Install desktop environment ****" \
|
||||
&& apt-get install -y \
|
||||
fonts-vlgothic \
|
||||
gedit \
|
||||
imagemagick \
|
||||
msttcorefonts \
|
||||
xdg-utils \
|
||||
xfce4 \
|
||||
xfce4-terminal \
|
||||
# Delete these as they are not needed at all
|
||||
&& rm -f \
|
||||
/usr/share/applications/software-properties-drivers.desktop \
|
||||
/usr/share/applications/xfce4-about.desktop \
|
||||
/usr/share/applications/xfce4-session-logout.desktop \
|
||||
# Hide these apps. They can be displayed if a user really wants them.
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/xfce4-accessibility-settings.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/xfce4-color-settings.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/xfce4-mail-reader.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/xfce4-web-browser.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/vim.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/thunar-settings.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/thunar.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/pavucontrol.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/x11vnc.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/display-im6.q16.desktop \
|
||||
# These are named specifically for Debain
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/debian-xterm.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/debian-uxterm.desktop \
|
||||
# Force these apps to be "System" Apps rather than "Categories=System;Utility;Core;GTK;Filesystem;"
|
||||
&& sed -i 's/^Categories=.*$/Categories=System;/' /usr/share/applications/xfce4-appfinder.desktop \
|
||||
&& sed -i 's/^Categories=.*$/Categories=System;/' /usr/share/applications/thunar-bulk-rename.desktop \
|
||||
&& sed -i 's/^Categories=.*$/Categories=System;/' /usr/share/applications/org.gnome.gedit.desktop \
|
||||
&& \
|
||||
echo "**** Install WoL Manager requirements ****" \
|
||||
&& apt-get install -y \
|
||||
tcpdump \
|
||||
xprintidle \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& apt-get clean autoclean -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/tmp/* \
|
||||
/tmp/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Add support for flatpaks
|
||||
ENV \
|
||||
XDG_DATA_DIRS="/home/default/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share/:/usr/share/"
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
&& \
|
||||
echo "**** Install flatpak support ****" \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
flatpak \
|
||||
gnome-software-plugin-flatpak \
|
||||
&& \
|
||||
echo "**** Configure flatpak ****" \
|
||||
&& flatpak remote-add flathub https://flathub.org/repo/flathub.flatpakrepo \
|
||||
&& dpkg-statoverride --update --add root root 0755 /usr/bin/bwrap \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& apt-get clean autoclean -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/tmp/* \
|
||||
/tmp/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# TODO: Deprecate neko
|
||||
# Install Neko server
|
||||
COPY --from=m1k1o/neko:base /usr/bin/neko /usr/bin/neko
|
||||
COPY --from=m1k1o/neko:base /var/www /var/www
|
||||
|
||||
# Install Web Frontend
|
||||
ARG FRONTEND_VERSION=a8eb92f
|
||||
RUN \
|
||||
echo "**** Fetch Web Frontend ****" \
|
||||
&& mkdir -p /opt \
|
||||
&& cd /opt \
|
||||
&& rm -rf /opt/frontend \
|
||||
&& git clone https://github.com/Steam-Headless/frontend.git --branch master /opt/frontend \
|
||||
&& cd /opt/frontend \
|
||||
&& git checkout ${FRONTEND_VERSION} 2> /dev/null \
|
||||
&& git submodule init \
|
||||
&& git submodule update --depth 1 --recursive \
|
||||
&& rm -rf /opt/frontend/.git \
|
||||
&& \
|
||||
echo "**** Configure Web Frontend ****" \
|
||||
&& echo '<!DOCTYPE html>' > /opt/frontend/index.html \
|
||||
&& echo '<html><head><meta http-equiv="refresh" content="0;url=./web/"></head><body><p>If you are not redirected, <a href="./web/">click here</a>.</p></body></html>' >> /opt/frontend/index.html \
|
||||
&& chmod -R 755 /opt/frontend \
|
||||
&& convert /opt/frontend/web/images/icons/novnc-ios-180.png -resize "128x128" /tmp/steam-headless.png \
|
||||
&& xdg-icon-resource install --novendor --size 128 /tmp/steam-headless.png \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& rm -f /tmp/steam-headless.png
|
||||
|
||||
# Install Websockify
|
||||
ARG WEBSOCKETIFY_VERSION=0.11.0
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
&& \
|
||||
echo "**** Install Websockify dependencies ****" \
|
||||
&& apt-get install -y \
|
||||
python3-numpy \
|
||||
python3-requests \
|
||||
python3-jwcrypto \
|
||||
python3-redis \
|
||||
&& \
|
||||
echo "**** Fetch Websockify ****" \
|
||||
&& cd /tmp \
|
||||
&& wget -O /tmp/websockify.tar.gz https://github.com/novnc/websockify/archive/v${WEBSOCKETIFY_VERSION}.tar.gz \
|
||||
&& \
|
||||
echo "**** Extract Websockify ****" \
|
||||
&& cd /tmp \
|
||||
&& tar -xvf /tmp/websockify.tar.gz \
|
||||
&& \
|
||||
echo "**** Install Websockify to Web Frontend path ****" \
|
||||
&& cd /tmp \
|
||||
&& mv -v /tmp/websockify-${WEBSOCKETIFY_VERSION} /opt/frontend/utils/websockify \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& apt-get clean autoclean -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/tmp/websockify-* \
|
||||
/tmp/websockify.tar.gz
|
||||
|
||||
# Setup audio streaming deps
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
&& \
|
||||
echo "**** Install audio streaming deps ****" \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
bzip2 \
|
||||
gstreamer1.0-alsa \
|
||||
gstreamer1.0-gl \
|
||||
gstreamer1.0-gtk3 \
|
||||
gstreamer1.0-libav \
|
||||
gstreamer1.0-plugins-bad \
|
||||
gstreamer1.0-plugins-base \
|
||||
gstreamer1.0-plugins-good \
|
||||
gstreamer1.0-plugins-ugly \
|
||||
gstreamer1.0-pulseaudio \
|
||||
gstreamer1.0-qt5 \
|
||||
gstreamer1.0-tools \
|
||||
gstreamer1.0-vaapi \
|
||||
gstreamer1.0-x \
|
||||
libgstreamer1.0-0 \
|
||||
libncursesw5 \
|
||||
libopenal1 \
|
||||
libsdl-image1.2 \
|
||||
libsdl-ttf2.0-0 \
|
||||
libsdl1.2debian \
|
||||
libsndfile1 \
|
||||
ucspi-tcp \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& apt-get clean autoclean -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/tmp/* \
|
||||
/tmp/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Setup video streaming deps
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
&& \
|
||||
echo "**** Install Intel media drivers and VAAPI ****" \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
intel-media-va-driver-non-free \
|
||||
i965-va-driver-shaders \
|
||||
libva2 \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& apt-get clean autoclean -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/tmp/* \
|
||||
/tmp/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install tools for monitoring hardware
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
&& \
|
||||
echo "**** Install useful HW monitoring tools ****" \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
cpu-x \
|
||||
htop \
|
||||
vainfo \
|
||||
vdpauinfo \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& apt-get clean autoclean -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/tmp/* \
|
||||
/tmp/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install Sunshine
|
||||
COPY --from=lizardbyte/sunshine:b00d7af-debian-bookworm /sunshine.deb /usr/src/sunshine.deb
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
&& \
|
||||
echo "**** Install Sunshine requirements ****" \
|
||||
&& apt-get install -y \
|
||||
va-driver-all \
|
||||
&& \
|
||||
echo "**** Install Sunshine ****" \
|
||||
&& apt-get install -y \
|
||||
/usr/src/sunshine.deb \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& apt-get clean autoclean -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/tmp/* \
|
||||
/tmp/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install Steam
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
&& \
|
||||
echo "**** Install Steam ****" \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
steam \
|
||||
&& ln -sf /usr/games/steam /usr/bin/steam \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& apt-get clean autoclean -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/tmp/* \
|
||||
/tmp/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Various other tools
|
||||
ARG DUMB_INIT_VERSION=1.2.5
|
||||
RUN \
|
||||
echo "**** Install dumb-init ****" \
|
||||
&& wget --no-check-certificate --no-cookies --quiet \
|
||||
-O /usr/bin/dumb-init \
|
||||
https://github.com/Yelp/dumb-init/releases/download/v${DUMB_INIT_VERSION}/dumb-init_${DUMB_INIT_VERSION}_x86_64 \
|
||||
&& chmod +x /usr/bin/dumb-init \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Add FS overlay
|
||||
COPY overlay /
|
||||
|
||||
# Set display environment variables
|
||||
ENV \
|
||||
DISPLAY_CDEPTH="24" \
|
||||
DISPLAY_REFRESH="120" \
|
||||
DISPLAY_SIZEH="900" \
|
||||
DISPLAY_SIZEW="1600" \
|
||||
DISPLAY_VIDEO_PORT="DFP" \
|
||||
DISPLAY=":55"
|
||||
ENV \
|
||||
NVIDIA_DRIVER_CAPABILITIES="all" \
|
||||
NVIDIA_VISIBLE_DEVICES="all"
|
||||
|
||||
# Set container configuration environment variables
|
||||
ENV \
|
||||
MODE="primary" \
|
||||
WEB_UI_MODE="vnc" \
|
||||
ENABLE_VNC_AUDIO="true" \
|
||||
NEKO_PASSWORD=neko \
|
||||
NEKO_PASSWORD_ADMIN=admin \
|
||||
ENABLE_STEAM="true" \
|
||||
STEAM_ARGS="-silent" \
|
||||
ENABLE_SUNSHINE="true" \
|
||||
ENABLE_EVDEV_INPUTS="false" \
|
||||
ENABLE_WOL_POWER_MANAGER="false"
|
||||
|
||||
# Configure required ports
|
||||
ENV \
|
||||
PORT_NOVNC_WEB="8083" \
|
||||
NEKO_NAT1TO1=""
|
||||
|
||||
# Expose the required ports
|
||||
EXPOSE 8083
|
||||
|
||||
# Set entrypoint
|
||||
RUN chmod +x /entrypoint.sh
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
57
README.md
@@ -1,41 +1,74 @@
|
||||
# Headless Steam Service
|
||||
|
||||
Play your games in the browser with audio. Connect another device and use it with Steam Remote Play. Easily deploy a Steam Docker instance in seconds.
|
||||

|
||||
|
||||
Remote Game Streaming Server.
|
||||
|
||||
Play your games either in the browser with audio or via Steam Link or Moonlight. Play from another Steam Client with Steam Remote Play.
|
||||
|
||||
Easily deploy a Steam Docker instance in seconds.
|
||||
|
||||
## Features:
|
||||
- Steam Client configured for running on Linux with Proton
|
||||
- Moonlight compatible server for easy remote desktop streaming
|
||||
- One click installation of EmeDeck, Heroic and Lutris
|
||||
- Full video/audio noVNC web access to a Xfce4 Desktop
|
||||
- NVIDIA GPU support
|
||||
- NVIDIA, AMD and Intel GPU support
|
||||
- Full controller support
|
||||
- Support for Flatpak and Appimage installation
|
||||
- Root access
|
||||
- SSH server for remote terminal access
|
||||
- Based on Debian Bookworm
|
||||
|
||||
---
|
||||
## Notes:
|
||||
|
||||
### ADDITIONAL SOFTWARE:
|
||||
If you wish to install additional applications, you can generate a
|
||||
script inside the `~/init.d` directory ending with ".sh". This will be executed on the container startup.
|
||||
If you wish to install additional applications, you can generate a script inside the `~/init.d` directory ending with ".sh".
|
||||
This will be executed on the container startup.
|
||||
|
||||
### STORAGE PATHS:
|
||||
Everything that you wish to save in this container should be stored in the home directory or a docker container mount that you have specified. All files that are store outside your home directory are not persistent and will be wiped if there is an update of the container or you change something in the template.
|
||||
Everything that you wish to save in this container should be stored in the home directory or a docker container mount that you have specified.
|
||||
All files that are store outside your home directory are not persistent and will be wiped if there is an update of the container or you change something in the template.
|
||||
|
||||
### GAMES LIBRARY:
|
||||
It is recommended that you mount your games library to `/games` and configure Steam to add that path.
|
||||
It is recommended that you mount your games library to `/mnt/games` and configure Steam to add that path.
|
||||
|
||||
### AUTO START APPLICATIONS:
|
||||
In this container, Steam is configured to automatically start. If you wish to add additional services to automatically start, add them under **Applications > Settings > Session and Startup** in the WebUI.
|
||||
In this container, Steam is configured to automatically start. If you wish to add additional services to automatically start,
|
||||
add them under **Applications > Settings > Session and Startup** in the WebUI.
|
||||
|
||||
### NETWORK MODE:
|
||||
If you want to use the container as a Steam Remote Play (previously "In Home Streaming") host device you should create a custom network and assign this container it's own IP, if you don't do this the traffic will be routed through the internet since Steam thinks you are on a different network.
|
||||
|
||||
### USING HOST X SERVER:
|
||||
If your host is already running X, you can just use that. To do this, be sure to configure:
|
||||
- DISPLAY=:0
|
||||
**(Variable)** - *Configures the sceen to use the primary display. Set this to whatever your host is using*
|
||||
- MODE=secondary
|
||||
**(Variable)** - *Configures the container to not start an X server of its own*
|
||||
- HOST_DBUS=true
|
||||
**(Variable)** - *Optional - Configures the container to use the host dbus process*
|
||||
- /run/dbus:/run/dbus:ro
|
||||
**(Mount)** - *Optional - Configures the container to use the host dbus process*
|
||||
|
||||
|
||||
---
|
||||
## Running:
|
||||
## Installation:
|
||||
- [Docker Compose](./docs/docker-compose.md)
|
||||
- [Unraid](./docs/unraid.md)
|
||||
- [Ubuntu Server](./docs/ubuntu-server.md)
|
||||
|
||||
|
||||
---
|
||||
## Running locally:
|
||||
|
||||
For a development environment, I have created a script in the devops directory.
|
||||
|
||||
|
||||
---
|
||||
## TODO:
|
||||
- Configure xorg.conf with no NVIDIA GPU
|
||||
- Lock SSH access to user only (remove root access)
|
||||
- Remove SSH
|
||||
- Require user to enter password for sudo
|
||||
- Document how to run this container
|
||||
- Document how to run this container:
|
||||
- Other server OS
|
||||
- TrueNAS Scale
|
||||
|
||||
@@ -5,62 +5,132 @@
|
||||
# File Created: Saturday, 8th January 2022 2:34:23 pm
|
||||
# Author: Josh.5 (jsunnex@gmail.com)
|
||||
# -----
|
||||
# Last Modified: Monday, 10th January 2022 11:04:51 pm
|
||||
# Modified By: Josh.5 (jsunnex@gmail.com)
|
||||
# Last Modified: Tuesday, 8th February 2022 8:00:29 am
|
||||
# Modified By: Console and webGui login account (jsunnex@gmail.com)
|
||||
###
|
||||
|
||||
script_path=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd );
|
||||
project_base_path=$(realpath ${script_path}/..);
|
||||
|
||||
|
||||
if [[ ${1} == "stop" ]]; then
|
||||
docker stop steam-headless
|
||||
docker rm steam-headless
|
||||
# Parse params
|
||||
additional_docker_params=""
|
||||
container_name="steam"
|
||||
tag="develop"
|
||||
for ARG in ${@}; do
|
||||
case ${ARG} in
|
||||
*primary)
|
||||
primary="true";
|
||||
;;
|
||||
*nvidia)
|
||||
nvidia="true";
|
||||
;;
|
||||
*fb)
|
||||
framebuffer="true";
|
||||
;;
|
||||
*br0)
|
||||
network="br0";
|
||||
;;
|
||||
stop)
|
||||
script_mode="stop"
|
||||
;;
|
||||
tail)
|
||||
script_mode="tail"
|
||||
;;
|
||||
user)
|
||||
script_mode="user"
|
||||
;;
|
||||
root)
|
||||
script_mode="root"
|
||||
;;
|
||||
*arch)
|
||||
tag="arch";
|
||||
;;
|
||||
*debian)
|
||||
tag="debian";
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
done
|
||||
if [[ "${primary}" == "true" ]]; then
|
||||
container_name="${container_name}-p"
|
||||
additional_docker_params="${additional_docker_params} -e MODE=primary"
|
||||
hostx="false"
|
||||
elif [[ "${framebuffer}" == "true" ]]; then
|
||||
# TODO: Enable xvfb
|
||||
container_name="${container_name}-fb"
|
||||
additional_docker_params="${additional_docker_params} -e MODE=framebuffer"
|
||||
else
|
||||
container_name="${container_name}-s"
|
||||
additional_docker_params="${additional_docker_params} -e MODE=secondary"
|
||||
fi
|
||||
if [[ "${nvidia}" == "true" ]]; then
|
||||
container_name="${container_name}-hw"
|
||||
additional_docker_params="${additional_docker_params} --runtime=nvidia"
|
||||
fi
|
||||
if [[ "${network}" == "br0" ]]; then
|
||||
additional_docker_params="${additional_docker_params} --network=br0 --ip='192.168.1.208'"
|
||||
else
|
||||
additional_docker_params="${additional_docker_params} --network=host"
|
||||
fi
|
||||
if [[ -e /dev/dri ]]; then
|
||||
additional_docker_params="${additional_docker_params} --device=/dev/dri"
|
||||
fi
|
||||
|
||||
|
||||
# If a mode was given, run that instead
|
||||
if [[ "${script_mode}" == "stop" ]]; then
|
||||
docker stop ${container_name}
|
||||
docker rm ${container_name}
|
||||
exit $?
|
||||
elif [[ ${1} == "tail" ]]; then
|
||||
docker logs -f steam-headless
|
||||
elif [[ "${script_mode}" == "tail" ]]; then
|
||||
docker logs -f ${container_name}
|
||||
exit $?
|
||||
elif [[ ${1} == "user" ]]; then
|
||||
docker exec -ti --user default steam-headless bash
|
||||
elif [[ "${script_mode}" == "user" ]]; then
|
||||
docker exec -ti --user default ${container_name} bash
|
||||
exit $?
|
||||
elif [[ ${1} == "root" ]]; then
|
||||
docker exec -ti --user 0 steam-headless bash
|
||||
elif [[ "${script_mode}" == "root" ]]; then
|
||||
docker exec -ti --user 0 ${container_name} bash
|
||||
exit $?
|
||||
fi
|
||||
|
||||
|
||||
docker stop steam-headless
|
||||
docker rm steam-headless
|
||||
# Stop previous instance
|
||||
docker stop ${container_name}
|
||||
docker rm ${container_name}
|
||||
sleep 1
|
||||
|
||||
|
||||
docker run -d --name='steam-headless' \
|
||||
--privileged=true \
|
||||
--net='br0' --ip='192.168.1.208' \
|
||||
--cpuset-cpus='3,9,4,10,5,11' \
|
||||
-e PUID="99" \
|
||||
-e PGID="100" \
|
||||
# Run
|
||||
cmd="docker run -d --name='${container_name}' \
|
||||
--privileged=true \
|
||||
-e PUID='99' \
|
||||
-e PGID='100' \
|
||||
-e UMASK='000' \
|
||||
-e USER_PASSWORD="password" \
|
||||
-e USER="default" \
|
||||
-e HOME="/home/test" \
|
||||
-e USER_HOME="/home/default" \
|
||||
-e TZ="Pacific/Auckland" \
|
||||
-e USER_LOCALES="en_US.UTF-8 UTF-8" \
|
||||
-e DISPLAY_CDEPTH="24" \
|
||||
-e DISPLAY_DPI="96" \
|
||||
-e DISPLAY_REFRESH="60" \
|
||||
-e DISPLAY_SIZEH="720" \
|
||||
-e DISPLAY_SIZEW="1280" \
|
||||
-e DISPLAY_VIDEO_PORT="DFP" \
|
||||
-e DISPLAY=":0" \
|
||||
-e NVIDIA_DRIVER_CAPABILITIES="all" \
|
||||
-e NVIDIA_VISIBLE_DEVICES="all" \
|
||||
-v "${project_base_path}/config/home/default":'/home/default':'rw' \
|
||||
--hostname='steam-headless' \
|
||||
-e USER_PASSWORD='password' \
|
||||
-e USER='default' \
|
||||
-e USER_HOME='/home/default' \
|
||||
-e TZ='Pacific/Auckland' \
|
||||
-e USER_LOCALES='en_US.UTF-8 UTF-8' \
|
||||
-e DISPLAY_CDEPTH='24' \
|
||||
-e DISPLAY_REFRESH='60' \
|
||||
-e DISPLAY_SIZEH='720' \
|
||||
-e DISPLAY_SIZEW='1280' \
|
||||
-e DISPLAY_VIDEO_PORT='DFP' \
|
||||
-e DISPLAY=':55' \
|
||||
-e NVIDIA_DRIVER_CAPABILITIES='all' \
|
||||
-e NVIDIA_VISIBLE_DEVICES='all' \
|
||||
-e ENABLE_VNC_AUDIO='false' \
|
||||
-v '${project_base_path}/config/home/default-${container_name}':'/home/default':'rw' \
|
||||
-v '/tmp/.X11-unix/':'/tmp/.X11-unix/':'rw' \
|
||||
-v '/dev/input':'/dev/input':'ro' \
|
||||
--hostname='${container_name}' \
|
||||
--add-host=${container_name}:127.0.0.1 \
|
||||
--shm-size=2G \
|
||||
--runtime=nvidia \
|
||||
josh5/steam-headless:latest
|
||||
${additional_docker_params} \
|
||||
josh5/steam-headless:${tag}"
|
||||
echo ${cmd}
|
||||
bash -c "${cmd}"
|
||||
|
||||
|
||||
docker logs -f steam-headless
|
||||
docker logs -f ${container_name}
|
||||
|
||||
113
docs/compose-files/.env
Normal file
@@ -0,0 +1,113 @@
|
||||
# ____ _
|
||||
# / ___| _ _ ___| |_ ___ _ __ ___
|
||||
# \___ \| | | / __| __/ _ \ '_ ` _ \
|
||||
# ___) | |_| \__ \ || __/ | | | | |
|
||||
# |____/ \__, |___/\__\___|_| |_| |_|
|
||||
# |___/
|
||||
#
|
||||
NAME='SteamHeadless'
|
||||
TZ='Pacific/Auckland'
|
||||
USER_LOCALES='en_US.UTF-8 UTF-8'
|
||||
DISPLAY=':55'
|
||||
SHM_SIZE='2G'
|
||||
## DOCKER_RUNTIME:
|
||||
## Options: ['runc', 'nvidia']
|
||||
## Description: The name of an implementation of OCI Runtime Spec
|
||||
## Available runtimes are listed when you run `docker info`.
|
||||
## Your system may have other options available. As a simple rule, if you are
|
||||
## using an NVIDIA GPU, set this to 'nvidia' for anything else, set this to 'runc'.
|
||||
DOCKER_RUNTIME='runc'
|
||||
|
||||
# ____ __ _ _ _ _
|
||||
# | _ \ ___ / _| __ _ _ _| | |_ | | | |___ ___ _ __
|
||||
# | | | |/ _ \ |_ / _` | | | | | __| | | | / __|/ _ \ '__|
|
||||
# | |_| | __/ _| (_| | |_| | | |_ | |_| \__ \ __/ |
|
||||
# |____/ \___|_| \__,_|\__,_|_|\__| \___/|___/\___|_|
|
||||
#
|
||||
#
|
||||
PUID='1000'
|
||||
PGID='1000'
|
||||
UMASK='000'
|
||||
USER_PASSWORD='password'
|
||||
|
||||
# __ __ _
|
||||
# | \/ | ___ __| | ___
|
||||
# | |\/| |/ _ \ / _` |/ _ \
|
||||
# | | | | (_) | (_| | __/
|
||||
# |_| |_|\___/ \__,_|\___|
|
||||
#
|
||||
#
|
||||
## MODE:
|
||||
## Options: ['primary', 'secondary']
|
||||
## Description: Steam Headless containers can run in a secondary mode that will only start
|
||||
## a Steam process that will then use the X server of either the host or another
|
||||
## Steam Headless container running in 'primary' mode.
|
||||
MODE='primary'
|
||||
|
||||
# ____ _
|
||||
# / ___| ___ _ ____ _(_) ___ ___ ___
|
||||
# \___ \ / _ \ '__\ \ / / |/ __/ _ \/ __|
|
||||
# ___) | __/ | \ V /| | (_| __/\__ \
|
||||
# |____/ \___|_| \_/ |_|\___\___||___/
|
||||
#
|
||||
#
|
||||
# Web UI
|
||||
## WEB_UI_MODE:
|
||||
## Options: ['vnc', 'neko', 'none']
|
||||
## Description: Configures the WebUI to use for accessing the virtual desktop.
|
||||
## Supported Modes: ['primary']
|
||||
WEB_UI_MODE='vnc'
|
||||
## ENABLE_VNC_AUDIO:
|
||||
## Options: ['true', 'false']
|
||||
## Description: Enables audio over for the VNC Web UI if 'WEB_UI_MODE' is set to 'vnc'.
|
||||
ENABLE_VNC_AUDIO='true'
|
||||
## PORT_NOVNC_WEB:
|
||||
## Description: Configure the port to use for the WebUI.
|
||||
PORT_NOVNC_WEB='8083'
|
||||
## NEKO_NAT1TO1:
|
||||
## Description: Configure nat1to1 for the neko WebUI if it is enabled by setting 'WEB_UI_MODE' to 'neko'.
|
||||
## This will need to be the IP address of the host.
|
||||
NEKO_NAT1TO1=''
|
||||
|
||||
# Steam
|
||||
## ENABLE_STEAM:
|
||||
## Options: ['true', 'false']
|
||||
## Description: Enable Steam to run on start. This will also cause steam to restart automatically if closed.
|
||||
## Supported Modes: ['primary', 'secondary']
|
||||
ENABLE_STEAM='true'
|
||||
## STEAM_ARGS:
|
||||
## Description: Additional steam execution arguments.
|
||||
#STEAM_ARGS='-silent -bigpicture'
|
||||
|
||||
# Sunshine
|
||||
## ENABLE_SUNSHINE:
|
||||
## Options: ['true', 'false']
|
||||
## Description: Enable Sunshine streaming service.
|
||||
## Supported Modes: ['primary']
|
||||
ENABLE_SUNSHINE='false'
|
||||
## SUNSHINE_USER:
|
||||
## Description: Set the Sunshine service username.
|
||||
#SUNSHINE_USER='admin'
|
||||
## SUNSHINE_PASS:
|
||||
## Description: Set the Sunshine service password.
|
||||
#SUNSHINE_PASS='admin'
|
||||
|
||||
# Xorg
|
||||
## ENABLE_EVDEV_INPUTS:
|
||||
## Available Options: ['true', 'false']
|
||||
## Description: Enable Keyboard and Mouse Passthrough. This will configure the Xorg server to catch all
|
||||
## evdev events for Keyboard, Mouse, etc.
|
||||
## Supported Modes: ['primary']
|
||||
ENABLE_EVDEV_INPUTS='true'
|
||||
|
||||
# Nvidia specific config (not required for non Nvidia GPUs)
|
||||
## NVIDIA_DRIVER_CAPABILITIES:
|
||||
## Options: ['all', 'compute', 'compat32', 'graphics', 'utility', 'video', 'display']
|
||||
## Description: Controls which driver libraries/binaries will be mounted inside the container.
|
||||
## Supported Modes: ['primary', 'secondary']
|
||||
NVIDIA_DRIVER_CAPABILITIES='all'
|
||||
## NVIDIA_DRIVER_CAPABILITIES:
|
||||
## Available Options: ['all', 'none', '<GPU UUID>']
|
||||
## Description: Controls which GPUs will be made accessible inside the container.
|
||||
## Supported Modes: ['primary', 'secondary']
|
||||
NVIDIA_VISIBLE_DEVICES='all'
|
||||
80
docs/compose-files/docker-compose.default.yml
Normal file
@@ -0,0 +1,80 @@
|
||||
---
|
||||
services:
|
||||
steam-headless:
|
||||
image: josh5/steam-headless:latest
|
||||
restart: unless-stopped
|
||||
runtime: ${DOCKER_RUNTIME}
|
||||
shm_size: ${SHM_SIZE}
|
||||
ipc: host # Could also be set to 'shareable'
|
||||
ulimits:
|
||||
nofile:
|
||||
soft: 1024
|
||||
hard: 524288
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
- SYS_ADMIN
|
||||
- SYS_NICE
|
||||
security_opt:
|
||||
- seccomp:unconfined
|
||||
- apparmor:unconfined
|
||||
|
||||
# NETWORK:
|
||||
hostname: ${NAME}
|
||||
extra_hosts:
|
||||
- "${NAME}:127.0.0.1"
|
||||
networks:
|
||||
external-macvlan:
|
||||
ipv4_address: ${CONTAINER_IP_ADDRESS}
|
||||
|
||||
# ENVIRONMENT:
|
||||
## Read all config variables from the .env file
|
||||
env_file: .env
|
||||
|
||||
# DEVICES:
|
||||
devices:
|
||||
# Use the host fuse device.
|
||||
- /dev/fuse
|
||||
# Add the host uinput device.
|
||||
- /dev/uinput
|
||||
# Add AMD/Intel HW accelerated video encoding/decoding devices (optional)
|
||||
#- /dev/dri
|
||||
# Ensure container access to devices 13:*
|
||||
device_cgroup_rules:
|
||||
- 'c 13:* rmw'
|
||||
|
||||
# VOLUMES:
|
||||
volumes:
|
||||
# The location of your home directory.
|
||||
- /opt/container-data/steam-headless/home/:/home/default/:rw
|
||||
|
||||
# The location where all games should be installed.
|
||||
# This path needs to be set as a library path in Steam after logging in.
|
||||
# Otherwise, Steam will store games in the home directory above.
|
||||
- /mnt/games/:/mnt/games/:rw
|
||||
|
||||
# The Xorg socket. This will be shared with other containers so they can access the X server.
|
||||
# Select only one option or leave commented out to not share the Xorg socket with any other Docker containers.
|
||||
# Option #1) Start a X server in the container to share with any other containers.
|
||||
#- /opt/container-data/steam-headless/.X11-unix/:/tmp/.X11-unix/:rw
|
||||
# Option #2) Use an existing X server running on the host.
|
||||
#- /tmp/.X11-unix/:/tmp/.X11-unix/:rw
|
||||
|
||||
# Pulse audio socket. This will be shared with other containers so they can access the audio sink.
|
||||
# Leave commented out to not share the pulse socket with any other Docker containers.
|
||||
#- /opt/container-data/steam-headless/pulse/:/tmp/pulse/:rw
|
||||
|
||||
# Input devices used for mouse and joypad support inside the container.
|
||||
- /dev/input/:/dev/input/:ro
|
||||
# Host udev data required for input devices
|
||||
- /run/udev/data/:/run/udev/data/:ro
|
||||
|
||||
# Store flatpak var files in a volume.
|
||||
- steam-headless-var-lib-flatpak:/var/lib/flatpak/:rw
|
||||
|
||||
volumes:
|
||||
steam-headless-var-lib-flatpak:
|
||||
|
||||
networks:
|
||||
external-macvlan:
|
||||
external: true
|
||||
name: ${NETWORK_NAME}
|
||||
56
docs/compose-files/docker-compose.privileged.yml
Normal file
@@ -0,0 +1,56 @@
|
||||
---
|
||||
services:
|
||||
steam-headless:
|
||||
image: josh5/steam-headless:latest
|
||||
restart: unless-stopped
|
||||
runtime: ${DOCKER_RUNTIME}
|
||||
## NOTE: This config uses privileged to access to host to be able to access the required devices
|
||||
privileged: true
|
||||
shm_size: ${SHM_SIZE}
|
||||
ipc: host # Could also be set to 'shareable'
|
||||
ulimits:
|
||||
nofile:
|
||||
soft: 1024
|
||||
hard: 524288
|
||||
|
||||
# NETWORK:
|
||||
## NOTE: If we do not use the host network, then physical device input is not possible
|
||||
## and your USB connected controllers will not work in steam games.
|
||||
network_mode: host
|
||||
hostname: ${NAME}
|
||||
extra_hosts:
|
||||
- "${NAME}:127.0.0.1"
|
||||
|
||||
# ENVIRONMENT:
|
||||
## Read all config variables from the .env file
|
||||
env_file: .env
|
||||
|
||||
# VOLUMES:
|
||||
volumes:
|
||||
# The location of your home directory.
|
||||
- /opt/container-data/steam-headless/home/:/home/default/:rw
|
||||
|
||||
# The location where all games should be installed.
|
||||
# This path needs to be set as a library path in Steam after logging in.
|
||||
# Otherwise, Steam will store games in the home directory above.
|
||||
- /mnt/games/:/mnt/games/:rw
|
||||
|
||||
# The Xorg socket. This will be shared with other containers so they can access the X server.
|
||||
# Select only one option:
|
||||
# Option #1) Start a X server in the container to share with any other containers.
|
||||
#- /opt/container-data/steam-headless/.X11-unix/:/tmp/.X11-unix/:rw
|
||||
# Option #2) Use an existing X server running on the host.
|
||||
#- /tmp/.X11-unix/:/tmp/.X11-unix/:rw
|
||||
|
||||
# Pulse audio socket. This will be shared with other containers so they can access the audio sink.
|
||||
# Leave commented out to not share the pulse socket with any other Docker containers.
|
||||
#- /opt/container-data/steam-headless/pulse/:/tmp/pulse/:rw
|
||||
|
||||
# Input devices used for mouse and joypad support inside the container.
|
||||
- /dev/input/:/dev/input/:ro
|
||||
|
||||
# Store flatpak var files in a volume.
|
||||
- steam-headless-var-lib-flatpak:/var/lib/flatpak/:rw
|
||||
|
||||
volumes:
|
||||
steam-headless-var-lib-flatpak:
|
||||
113
docs/docker-compose.md
Normal file
@@ -0,0 +1,113 @@
|
||||
# Docker Compose
|
||||
|
||||
Follow these instructions to configure a docker-compose.yml for your system.
|
||||
|
||||
> __Note__
|
||||
>
|
||||
> These instructions assume that you have docker and docker-compose installed for your system.
|
||||
>
|
||||
> Depending on how you have installed this, the commands to execute docker compose may vary.
|
||||
|
||||
|
||||
## PREPARE DIRECTORIES:
|
||||
|
||||
> __Warning__
|
||||
>
|
||||
> These commands are meant to be run as your user. Do not run them as root.
|
||||
>
|
||||
> If you do run these commands as root, you may need to manually fix the permissions and ownership after.
|
||||
|
||||
Create a directory for your service:
|
||||
```shell
|
||||
sudo mkdir -p /opt/container-services/steam-headless
|
||||
sudo chown -R $(id -u):$(id -g) /opt/container-services/steam-headless
|
||||
```
|
||||
|
||||
Create a directory for your service config data:
|
||||
```shell
|
||||
sudo mkdir -p /opt/container-data/steam-headless/{home,.X11-unix,pulse}
|
||||
sudo chown -R $(id -u):$(id -g) /opt/container-data/steam-headless
|
||||
```
|
||||
|
||||
(Optional) Create a directory for your game install location:
|
||||
```shell
|
||||
sudo mkdir /mnt/games
|
||||
sudo chmod -R 777 /mnt/games
|
||||
sudo chown -R $(id -u):$(id -g) /mnt/games
|
||||
```
|
||||
|
||||
Create a Steam Headless `/opt/container-services/steam-headless/docker-compose.yml` file.
|
||||
|
||||
Populate this file with the contents of the default [Docker Compose File](./compose-files/docker-compose.default.yml).
|
||||
|
||||
|
||||
## CONFIGURE HOST:
|
||||
|
||||
It is recommended that you configure this container to use a Macvlan network. If you know what you are doing, you can also use an IPvlan or Host, but I will not be covering that setup in this documentation.
|
||||
|
||||
To simplify the setup process and allow you to reuse the created Macvlan for other containers, we will create this Macvlan manually rather than have Docker compose handle it. If you know what you are doing with Docker compose and you would rather have the Macvlan managed there, feel free to do so. Otherwise run this command and carry on with the setup:
|
||||
|
||||
### 1) Discover your parent network:
|
||||
To find the parent network device, run the command `ip address show`. Find the device that has the IP address of your Host server.
|
||||
```
|
||||
root@Tower:~# ip address show
|
||||
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
|
||||
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
|
||||
inet 127.0.0.1/8 scope host lo
|
||||
valid_lft forever preferred_lft forever
|
||||
inet6 ::1/128 scope host
|
||||
valid_lft forever preferred_lft forever
|
||||
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
|
||||
link/ipip 0.0.0.0 brd 0.0.0.0
|
||||
3: eth0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc fq master br0 state UP group default qlen 1000
|
||||
link/ether 7c:11:a9:b1:15:b9 brd ff:ff:ff:ff:ff:ff
|
||||
4: eth0.1@eth0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc noqueue master br0.1 state UP group default qlen 1000
|
||||
link/ether 7c:11:a9:b1:15:b9 brd ff:ff:ff:ff:ff:ff
|
||||
5: eth0.3@eth0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc noqueue master br0.3 state UP group default qlen 1000
|
||||
link/ether 7c:11:a9:b1:15:b9 brd ff:ff:ff:ff:ff:ff
|
||||
6: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
|
||||
link/ether 7c:11:a9:b1:15:b9 brd ff:ff:ff:ff:ff:ff
|
||||
inet 192.168.1.43/24 brd 192.168.1.255 scope global dynamic noprefixroute br0
|
||||
valid_lft 440sec preferred_lft 365sec
|
||||
```
|
||||
In this example output, I will select br0 as the parent network device which has the IP address of "192.168.1.43".
|
||||
|
||||
### 2) Create a macvlan Docker network
|
||||
```
|
||||
# Set the parent network device.
|
||||
NETWORK_PARTENT=br0
|
||||
# Name this whatever you like, but ensure you update the `.env` file below to match.
|
||||
NETWORK_NAME=steam-headless-vlan
|
||||
# Choose a network subnet and gateway that matches your host network
|
||||
NETWORK_SUBNET=192.168.1.0/24
|
||||
NETWORK_GATEWAY=192.168.1.1
|
||||
# Execute the docker network create command
|
||||
sudo docker network create -d macvlan \
|
||||
--subnet=${NETWORK_SUBNET:?} \
|
||||
--gateway=${NETWORK_GATEWAY:?} \
|
||||
-o parent=${NETWORK_PARTENT:?} \
|
||||
${NETWORK_NAME:?}
|
||||
```
|
||||
|
||||
|
||||
## CONFIGURE ENV:
|
||||
|
||||
Create a Steam Headless `/opt/container-services/steam-headless/.env` file with the contents found in this example [Environment File](./compose-files/.env).
|
||||
|
||||
Edit these variables as required.
|
||||
|
||||
## EXECUTE:
|
||||
|
||||
Navigate to your compose location and execute it.
|
||||
```shell
|
||||
cd /opt/container-services/steam-headless
|
||||
sudo docker-compose up -d --force-recreate
|
||||
```
|
||||
|
||||
After container executes successfully, navigate to your docker host URL in your browser on port 8083 and click connect.
|
||||
http://<host-ip>:8083/
|
||||

|
||||
|
||||
If using a `/mnt/games` volume mount, wait until Steam installs and executes, then restart the container. This step
|
||||
is necessary to create the required steamapps folder in the /mnt/games volume after initial installation. If this
|
||||
doesn't occur, you will receive a "disk write error" when trying to install to this location.
|
||||
BIN
docs/images/install-steam-headless-unraid-ca.png
Normal file
|
After Width: | Height: | Size: 163 KiB |
BIN
docs/images/unraid-amd-plugin.png
Normal file
|
After Width: | Height: | Size: 77 KiB |
BIN
docs/images/unraid-nvidia-plugin.png
Normal file
|
After Width: | Height: | Size: 118 KiB |
BIN
docs/images/unraid-steam-headless-configure-network-as-host.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
docs/images/unraid-steam-headless-install-uinput-plugin.png
Normal file
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 64 KiB |
25
docs/k8s-files/pvc.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: games
|
||||
spec:
|
||||
storageClassName: ssd #Adjust your storageclass as needed
|
||||
volumeMode: Filesystem
|
||||
resources:
|
||||
requests:
|
||||
storage: 400Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: home
|
||||
spec:
|
||||
volumeMode: Filesystem
|
||||
storageClassName: nvme-replicated #Adjust your storageclass as needed
|
||||
resources:
|
||||
requests:
|
||||
storage: 50Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
96
docs/k8s-files/statefulset.yaml
Normal file
@@ -0,0 +1,96 @@
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: steam-headless
|
||||
spec:
|
||||
serviceName: "steam-headless"
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: steam-headless
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: steam-headless
|
||||
spec:
|
||||
hostNetwork: true
|
||||
securityContext:
|
||||
fsGroup: 1000
|
||||
containers:
|
||||
- name: steam-headless
|
||||
securityContext:
|
||||
privileged: true
|
||||
image: josh5/steam-headless:latest
|
||||
resources: #Change CPU and Memory below
|
||||
requests:
|
||||
memory: "24G"
|
||||
cpu: "6"
|
||||
limits:
|
||||
memory: "24G"
|
||||
cpu: "6"
|
||||
nvidia.com/gpu: 1 #If you're using a nvidia GPU, add it here
|
||||
volumeMounts:
|
||||
- name: home-dir
|
||||
mountPath: /home/default/
|
||||
- name: games-dir
|
||||
mountPath: /mnt/games/
|
||||
- name: input-devices
|
||||
mountPath: /dev/input/
|
||||
- name: dshm
|
||||
mountPath: /dev/shm
|
||||
env: #Environmental Vars
|
||||
- name: NAME
|
||||
value: 'SteamHeadless'
|
||||
- name: TZ
|
||||
value: 'America/New_York'
|
||||
- name: USER_LOCALES
|
||||
value: 'en_US.UTF-8 UTF-8'
|
||||
- name: DISPLAY
|
||||
value: ':55'
|
||||
- name: SHM_SIZE
|
||||
value: '2G'
|
||||
- name: DOCKER_RUNTIME
|
||||
value: 'nvidia'
|
||||
- name: PUID
|
||||
value: '1000'
|
||||
- name: PGID
|
||||
value: '1000'
|
||||
- name: UMASK
|
||||
value: '000'
|
||||
- name: USER_PASSWORD
|
||||
value: 'password' #changeme
|
||||
- name: MODE
|
||||
value: 'primary'
|
||||
- name: WEB_UI_MODE
|
||||
value: 'none'
|
||||
- name: ENABLE_VNC_AUDIO
|
||||
value: 'false'
|
||||
- name: PORT_NOVNC_WEB
|
||||
value: '8083'
|
||||
- name: NEKO_NAT1TO1
|
||||
value: ''
|
||||
- name: ENABLE_SUNSHINE
|
||||
value: 'true'
|
||||
- name: SUNSHINE_USER
|
||||
value: 'sam'
|
||||
- name: SUNSHINE_PASS
|
||||
value: 'password'
|
||||
- name: ENABLE_EVDEV_INPUTS
|
||||
value: 'true'
|
||||
- name: NVIDIA_DRIVER_CAPABILITIES
|
||||
value: 'all'
|
||||
- name: NVIDIA_VISIBLE_DEVICES
|
||||
value: 'all'
|
||||
volumes:
|
||||
- name: home-dir
|
||||
persistentVolumeClaim:
|
||||
claimName: home
|
||||
- name: games-dir
|
||||
persistentVolumeClaim:
|
||||
claimName: games
|
||||
- name: input-devices
|
||||
hostPath:
|
||||
path: /dev/input/
|
||||
- name: dshm
|
||||
emptyDir:
|
||||
medium: Memory
|
||||
16
docs/k8s.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# Kubernetes
|
||||
|
||||
Have a cluster at home and want to add steam headless to it?
|
||||
|
||||
Requirements
|
||||
- NVIDIA Device plugin (if using nvidia GPU) https://github.com/NVIDIA/k8s-device-plugin
|
||||
- A storageclass
|
||||
|
||||
Tasks
|
||||
1. Configure the statefulset to your liking. Things to note:
|
||||
- CPU & Memory
|
||||
- Env vars (see compose-files/.env for documentation)
|
||||
2. Change the PVC to your liking. Things to note:
|
||||
- Storage Class
|
||||
- Size
|
||||
3. Deploy it: `kubectl create -f k8s-files/*`
|
||||
30
docs/troubleshooting.md
Normal file
@@ -0,0 +1,30 @@
|
||||
## Flatpaks not working
|
||||
|
||||
Steam runs with Flatpak. These Flatpaks are instlled into the `default` user's home directory so they persist between container updates. Sometimes Flatpaks can get into a knot between major Steam Headless updates. In such cases, it may not work correctly. To fix this, just delete the Flatpak runtime in your `default` user's home directory a restart the container.
|
||||
|
||||
1) Stop the container.
|
||||
2) Delete the directory `<SteamHeadless Home>/.local/share/flatpak`
|
||||
3) Re-create the container. Don't just restart it. This will trigger an update of the required Flatpak runtimes in the home directory.
|
||||
4) Reinstall any missing Flatpaks from the Software app.
|
||||
|
||||
Once your Flatpak refresh is complete, everything should work correctly and your configuration for each application should have remained intact.
|
||||
|
||||
## An error occurred while installing <game>: "disk write error"
|
||||
|
||||

|
||||
|
||||
1) Stop the container
|
||||
2) Verify your mounted /mnt/games volume is owned by the executing UID/GID, and 777 permissions are set.
|
||||
3) Verify the `steamapps` directory exists within the library location.
|
||||
|
||||
> __Note__
|
||||
>
|
||||
> The directory in the below commands are the default /mnt/games library locations installed upon first execution of this container.
|
||||
>
|
||||
> Depending on how you have installed this, the directory path may vary.
|
||||
|
||||
```shell
|
||||
sudo mkdir /mnt/games/GameLibrary/SteamLibrary/steamapps
|
||||
sudo chmod -R 777 /mnt/games
|
||||
sudo chown -R $(id -u):$(id -g) /mnt/games
|
||||
```
|
||||
22
docs/ubuntu-server.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Ubuntu Server
|
||||
|
||||
Follow these instructions to install Steam Headless on Ubuntu Server.
|
||||
|
||||
> __Note__
|
||||
>
|
||||
> This assumes that your Ubuntu Server has not be configured to run any desktop environment!
|
||||
>
|
||||
> This will not work with Ubuntu Desktop.
|
||||
|
||||
|
||||
## INSTALL DOCKER:
|
||||
|
||||
Install docker-ce to your Ubuntu server following the [official instrctions](https://docs.docker.com/engine/install/ubuntu/).
|
||||
|
||||
Ensure you install the `docker-compose-plugin` mentioned within these instructions
|
||||
|
||||
|
||||
## CONFIGURE DOCKER COMPOSE:
|
||||
|
||||
Once you have installed docker, follow the [Compose Files](./docker-compose.md) section and select the right configuration file for your hardware.
|
||||
|
||||
58
docs/unraid.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# Unraid
|
||||
|
||||
Follow these instructions to install Steam Headless on Unraid
|
||||
|
||||
## CONTAINER TEMPLATE:
|
||||
|
||||
1. Navigate to "**APPS**" tab.
|
||||
2. Search for "*steam-headless*"
|
||||
3. Select either **Install** or **Actions > Install** from the search result.
|
||||

|
||||
4. Configure the template as required.
|
||||
|
||||
|
||||
## GPU CONFIGURATION:
|
||||
|
||||
This container can use your dedicated GPU.
|
||||
In order for it to do this you need to have either the Nvidia-Driver or Radeon-Top plugin installed.
|
||||
|
||||
### NVIDIA
|
||||
|
||||
1. Install the [Nvidia-Driver Plugin](https://forums.unraid.net/topic/98978-plugin-nvidia-driver/) by [ich777](https://forums.unraid.net/profile/72388-ich777/). This will maintain an up-to-date NVIDIA driver installation on your Unraid server.
|
||||

|
||||
2. Toggle the steam-headless Docker Container template editor to "**Advanced View**".
|
||||
3. In the "**Extra Parameters**" field, ensure that you have the "--runtime=nvidia" parameter added.
|
||||

|
||||
4. (Optional - This step is only necessary if you only multiple NVIDIA GPUs. If you have a single GPU, then leaving this as "all" is fine.) Expand the **Show more settings...** section near the bottom of the template. In the **Nvidia GPU UUID**: (NVIDIA_VISIBLE_DEVICES) variable, copy your GPU UUID (can be found in the Unraid Nvidia Plugin. See that forum thread for details).
|
||||
|
||||
### AMD
|
||||
|
||||
1. Install the [Radeon-Top Plugin](https://forums.unraid.net/topic/92865-support-ich777-amd-vendor-reset-coraltpu-hpsahba/) by [ich777](https://forums.unraid.net/profile/72388-ich777/).
|
||||

|
||||
2. Profit
|
||||
|
||||
|
||||
## ADDING CONTROLLER SUPPORT:
|
||||
|
||||
Unraid's Linux kernel by default does not have the modules required to support controller input. Steam requires these modules to be able to create the virtual "Steam Input Gamepad Emulation" device that it can then map buttons to.
|
||||
|
||||
[ich777](https://forums.unraid.net/profile/72388-ich777/) has kindly offered to build and maintain the required modules for the Unraid kernel as he already has a CI/CD pipeline in place and a small number of other kernel modules that he is maintaining for other projects. So a big thanks to him for that!
|
||||
|
||||
> __Note__
|
||||
>
|
||||
> This may no longer be required with Unraid v6.11 release (TBD). The required uinput module should be added to the kernel for that release.
|
||||
|
||||
1. Install the **uinput** plugin from the **Apps** tab.
|
||||

|
||||
2. The container will not be able to receive kernel events from the host unless the **Network Type:** is set to "*host*". Ensure that you container is configured this way.
|
||||

|
||||
|
||||
> __Warning__
|
||||
>
|
||||
> Be aware that, by default, this container requires at least 8083 available for the WebUI to work. It will also require any ports that Steam requires for Steam Remote Play.
|
||||
|
||||
You can override the default ports used by the container with these variables:
|
||||
- PORT_NOVNC_WEB (Default: 8083)
|
||||
- WEB_UI_MODE (Default: 'vnc' - Set to 'none' to disable the WebUI)
|
||||
|
||||
3. No server restart is required, however. Ensure that the **steam-headless** Docker container is recreated after installing the **uinput** plugin for it to be able to detect the newly added module.
|
||||
BIN
images/banner.jpg
Normal file
|
After Width: | Height: | Size: 328 KiB |
BIN
images/disk_write_error.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
images/vnc_connect.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
@@ -1,12 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
###
|
||||
# File: entrypoint.sh
|
||||
# Project: docker-steamos
|
||||
# Project: docker-steam-headless
|
||||
# File Created: Saturday, 8th January 2022 7:08:46 pm
|
||||
# Author: Josh.5 (jsunnex@gmail.com)
|
||||
# -----
|
||||
# Last Modified: Tuesday, 11th January 2022 1:02:16 am
|
||||
# Modified By: Josh.5 (jsunnex@gmail.com)
|
||||
# Last Modified: Saturday, 22nd January 2022 8:03:33 pm
|
||||
# Modified By: Console and webGui login account (jsunnex@gmail.com)
|
||||
###
|
||||
|
||||
set -e
|
||||
@@ -17,31 +17,52 @@ if [ ! -z "$@" ]; then
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Execute all init scripts
|
||||
for init_script in /scripts/*.sh ; do
|
||||
# Print the current version (if the file exists)
|
||||
if [[ -f /version.txt ]]; then
|
||||
cat /version.txt
|
||||
fi
|
||||
|
||||
# Execute all container init scripts
|
||||
for init_script in /etc/cont-init.d/*.sh ; do
|
||||
echo
|
||||
echo "[ ${init_script}: executing... ]"
|
||||
sed -i 's/\r$//' "${init_script}"
|
||||
source "${init_script}"
|
||||
echo -e "\e[34m[ ${init_script:?}: executing... ]\e[0m"
|
||||
sed -i 's/\r$//' "${init_script:?}"
|
||||
source "${init_script:?}"
|
||||
done
|
||||
touch /tmp/.first-run-init-scripts
|
||||
|
||||
# Execute any user generated init scripts
|
||||
mkdir -p ${USER_HOME}/init.d
|
||||
chown -R ${USER} ${USER_HOME}/init.d
|
||||
for user_init_script in ${USER_HOME}/init.d/*.sh ; do
|
||||
mkdir -p ${USER_HOME:?}/init.d
|
||||
chown -R ${USER:?} ${USER_HOME:?}/init.d
|
||||
for user_init_script in ${USER_HOME:?}/init.d/*.sh ; do
|
||||
|
||||
# Check that a file was found
|
||||
# (If no files exist in this directory, then user_init_script will be empty)
|
||||
if [[ -e "${user_init_script}" ]]; then
|
||||
if [[ -e "${user_init_script:?}" ]]; then
|
||||
|
||||
echo
|
||||
echo "[ USER:${user_init_script}: executing... ]"
|
||||
sed -i 's/\r$//' "${user_init_script}"
|
||||
source "${user_init_script}"
|
||||
echo -e "\e[34m[ USER:${user_init_script:?}: executing... ]\e[0m"
|
||||
sed -i 's/\r$//' "$(readlink -e "${user_init_script:?}")"
|
||||
|
||||
# Execute user script in sub process with 'set +e'.
|
||||
# This way if it is messed up, we dont get caught in an init loop.
|
||||
chmod +x "${user_init_script:?}"
|
||||
(
|
||||
set +e
|
||||
"${user_init_script:?}" || echo -e "\e[31mERROR: \e[33mFailed to execute user script '${user_init_script:?}'\e[0m"
|
||||
)
|
||||
|
||||
fi
|
||||
|
||||
done
|
||||
touch /tmp/.first-run-user-init-scripts
|
||||
|
||||
# Start supervisord
|
||||
echo
|
||||
echo "**** Starting supervisord ****";
|
||||
exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf --nodaemon
|
||||
echo "Logging all root services to '/var/log/supervisor/'"
|
||||
echo "Logging all user services to '/home/${USER:?}/.cache/log/'"
|
||||
echo
|
||||
mkdir -p /var/log/supervisor
|
||||
chmod a+rw /var/log/supervisor
|
||||
exec /usr/bin/supervisord -c /etc/supervisord.conf --nodaemon --user root
|
||||
|
||||
98
overlay/etc/cont-init.d/10-setup_user.sh
Normal file
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env bash
|
||||
###
|
||||
# File: 10-setup_user.sh
|
||||
# Project: cont-init.d
|
||||
# File Created: Friday, 12th January 2022 8:54:01 am
|
||||
# Author: Josh.5 (jsunnex@gmail.com)
|
||||
# -----
|
||||
# Last Modified: Monday, 10th July 2023 5:56:17 pm
|
||||
# Modified By: Console and webGui login account (jsunnex@gmail.com)
|
||||
###
|
||||
|
||||
PUID=${PUID:-99}
|
||||
PGID=${PGID:-100}
|
||||
UMASK=${UMASK:-000}
|
||||
USER_PASSWORD=${USER_PASSWORD:-password}
|
||||
|
||||
echo "**** Configure default user ****"
|
||||
|
||||
echo "Setting default user uid=${PUID}(${USER}) gid=${PGID}(${USER})"
|
||||
usermod -o -u "${PUID}" ${USER}
|
||||
groupmod -o -g "${PGID}" ${USER}
|
||||
|
||||
|
||||
echo "Adding default user to any additional required device groups"
|
||||
additional_groups=( video audio input pulse )
|
||||
for group_name in "${additional_groups[@]}"; do
|
||||
if [ $(getent group ${group_name:?}) ]; then
|
||||
echo "Adding user '${USER}' to group: '${group_name}'"
|
||||
usermod -aG ${group_name:?} ${USER}
|
||||
fi
|
||||
done
|
||||
device_nodes=( /dev/uinput /dev/input/event* /dev/dri/* )
|
||||
added_groups=""
|
||||
for dev in "${device_nodes[@]}"; do
|
||||
# Only process $dev if it's a character device
|
||||
if [[ ! -c "${dev}" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Get group name and ID
|
||||
dev_group=$(stat -c "%G" "${dev}")
|
||||
dev_gid=$(stat -c "%g" "${dev}")
|
||||
|
||||
# Dont add root
|
||||
if [[ "${dev_gid}" = 0 ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Create a name for the group ID if it does not yet already exist
|
||||
if [[ "${dev_group}" = "UNKNOWN" ]]; then
|
||||
dev_group="user-gid-${dev_gid}"
|
||||
groupadd -g $dev_gid "${dev_group}"
|
||||
fi
|
||||
|
||||
# Add group to user
|
||||
if [[ "${added_groups}" != *"${dev_group}"* ]]; then
|
||||
echo "Adding user '${USER}' to group: '${dev_group}' for device: ${dev}"
|
||||
usermod -aG ${dev_group} ${USER}
|
||||
added_groups=" ${added_groups} ${dev_group} "
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
echo "Setting umask to ${UMASK}";
|
||||
umask ${UMASK}
|
||||
|
||||
|
||||
# TODO: Move this to its own 'display' init script. It does not really belong here
|
||||
# Configure the 'XDG_RUNTIME_DIR' path
|
||||
echo "Create the user XDG_RUNTIME_DIR path '${XDG_RUNTIME_DIR}'"
|
||||
mkdir -p ${XDG_RUNTIME_DIR}
|
||||
# Ensure it is owned by the 'default' user
|
||||
chown -R ${PUID}:${PGID} ${XDG_RUNTIME_DIR}
|
||||
# Ensure only the 'default' user can access this directory
|
||||
chmod 700 ${XDG_RUNTIME_DIR}
|
||||
# Set the default background
|
||||
mkdir -p /etc/alternatives
|
||||
ln -sf /usr/share/backgrounds/steam.jpg /etc/alternatives/desktop-background
|
||||
chmod a+r /etc/alternatives/desktop-background
|
||||
|
||||
|
||||
# Setup services log path
|
||||
echo "Setting ownership of all log files in '${USER_HOME}/.cache/log'"
|
||||
mkdir -p "${USER_HOME}/.cache/log"
|
||||
chown -R ${PUID}:${PGID} "${USER_HOME}/.cache/log"
|
||||
|
||||
|
||||
# Set the root and user password
|
||||
echo "Setting root password"
|
||||
echo "root:${USER_PASSWORD}" | chpasswd
|
||||
echo "Setting user password"
|
||||
echo "${USER}:${USER_PASSWORD}" | chpasswd
|
||||
|
||||
# Set root XDG_RUNTIME_DIR path
|
||||
mkdir -p /tmp/runtime-root
|
||||
chown root:root /tmp/runtime-root
|
||||
|
||||
echo "DONE"
|
||||
26
overlay/etc/cont-init.d/11-setup_sysctl_values.sh
Normal file
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
###
|
||||
# File: 11-setup_sysctl_values.sh
|
||||
# Project: cont-init.d
|
||||
# File Created: Friday, 1st September 2023 3:56:17 pm
|
||||
# Author: Josh.5 (jsunnex@gmail.com)
|
||||
# -----
|
||||
# Last Modified: Monday, 1st September 2023 3:56:17 pm
|
||||
# Modified By: Console and webGui login account (jsunnex@gmail.com)
|
||||
###
|
||||
|
||||
echo "**** Configure some system kernel parameters ****"
|
||||
|
||||
|
||||
if [ "$(cat /proc/sys/vm/max_map_count)" -ge 524288 ]; then
|
||||
if [ -w "/proc/sys/vm/max_map_count" ]; then
|
||||
echo "Setting the maximum number of memory map areas a process can create to 524288"
|
||||
echo 524288 > /proc/sys/vm/max_map_count
|
||||
else
|
||||
echo "WARNING: Unable to set max_map_count on unprivileged container"
|
||||
fi
|
||||
else
|
||||
echo "NOTE: vm.max_map_count is already greater than '524288'"
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
32
overlay/etc/cont-init.d/30-configure_dbus.sh
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
# Configure dbus
|
||||
echo "**** Configure container dbus ****";
|
||||
|
||||
if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
|
||||
if [[ "${HOST_DBUS}" == "true" ]]; then
|
||||
echo "Container configured to use the host dbus";
|
||||
# Disable supervisord script
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/dbus.ini
|
||||
else
|
||||
echo "Container configured to run its own dbus";
|
||||
# Enable supervisord script
|
||||
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/dbus.ini
|
||||
# Configure dbus to run as USER
|
||||
sed -i "/ <user>/c\ <user>${USER}</user>" /usr/share/dbus-1/system.conf
|
||||
# Remove old dbus session
|
||||
rm -rf ${USER_HOME}/.dbus/session-bus/* 2> /dev/null
|
||||
# Remove old dbus pids
|
||||
mkdir -p /var/run/dbus
|
||||
chown -R ${PUID}:${PGID} /var/run/dbus/
|
||||
chmod -R 770 /var/run/dbus/
|
||||
# Generate a dbus machine ID
|
||||
dbus-uuidgen > /var/lib/dbus/machine-id
|
||||
# Remove old lockfiles
|
||||
find /var/run/dbus -name "pid" -exec rm -f {} \;
|
||||
fi
|
||||
else
|
||||
echo "Dbus service not available when container is run in 'secondary' mode."
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/dbus.ini
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
60
overlay/etc/cont-init.d/30-configure_udev.sh
Normal file
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env bash
|
||||
###
|
||||
# File: 30-configure_udev.sh
|
||||
# Project: cont-init.d
|
||||
# File Created: Friday, 12th January 2022 8:54:01 am
|
||||
# Author: Josh.5 (jsunnex@gmail.com)
|
||||
# -----
|
||||
# Last Modified: Tuesday, 4th October 2022 11:20:48 am
|
||||
# Modified By: Josh.5 (jsunnex@gmail.com)
|
||||
###
|
||||
|
||||
# Running udev only works in privileged container
|
||||
# Source: https://github.com/balena-io-playground/balena-base-images/
|
||||
tmp_mount='/tmp/privileged_test'
|
||||
mkdir -p "${tmp_mount}"
|
||||
if mount -t devtmpfs none "${tmp_mount}" &> /dev/null; then
|
||||
is_privileged=true
|
||||
umount "${tmp_mount}"
|
||||
else
|
||||
is_privileged=false
|
||||
fi
|
||||
rm -rf "${tmp_mount}"
|
||||
|
||||
|
||||
if [[ "${is_privileged}" == "true" ]]; then
|
||||
# Since this container may also be run with CAP_SYS_ADMIN, ensure we can actually execute "udevadm trigger"
|
||||
if [ ! -w /sys ]; then
|
||||
# Disable supervisord script since we are not able to write to sysfs
|
||||
echo "**** Disable udev - /sys is mounted RO ****";
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini
|
||||
elif [ ! -w /run/udev ]; then
|
||||
# Disable supervisord script since we are not able to write to udev/data path
|
||||
echo "**** Disable udev - /run/udev is mounted RO ****";
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini
|
||||
elif udevadm trigger &> /dev/null; then
|
||||
echo "**** Configure container to run udev management ****";
|
||||
# Enable supervisord script
|
||||
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/udev.ini
|
||||
# Configure udev permissions
|
||||
if [[ -f /lib/udev/rules.d/60-steam-input.rules ]]; then
|
||||
sed -i 's/MODE="0660"/MODE="0666"/' /lib/udev/rules.d/60-steam-input.rules
|
||||
fi
|
||||
else
|
||||
# Disable supervisord script since we are not able to execute "udevadm trigger"
|
||||
echo "**** Disable udev service due to privilege restrictions ****";
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini
|
||||
fi
|
||||
else
|
||||
# Disable supervisord script
|
||||
echo "**** Disable udev service ****";
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini
|
||||
fi
|
||||
|
||||
|
||||
if [[ -e /dev/uinput ]]; then
|
||||
echo "**** Ensure the default user has permission to r/w on input devices ****";
|
||||
chmod 0666 /dev/uinput
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
40
overlay/etc/cont-init.d/50-configure_pulseaudio.sh
Normal file
@@ -0,0 +1,40 @@
|
||||
|
||||
echo "**** Configure pulseaudio ****"
|
||||
|
||||
# Always enable the pulseaudio service
|
||||
echo "Enable pulseaudio service."
|
||||
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/pulseaudio.ini
|
||||
|
||||
if [ "${MODE}" == "s" ] | [ "${MODE}" == "secondary" ]; then
|
||||
echo "Configure pulseaudio as simple dummy audio"
|
||||
sed -i 's|^; autospawn.*$|autospawn = no|' /etc/pulse/client.conf
|
||||
sed -i 's|^; daemon-binary.*$|daemon-binary = /bin/true|' /etc/pulse/client.conf
|
||||
|
||||
sed -i 's|^; flat-volumes.*$|flat-volumes = yes|' /etc/pulse/daemon.conf
|
||||
else
|
||||
echo "Configure pulseaudio to pipe audio to a socket"
|
||||
|
||||
# Ensure pulseaudio directories have the correct permissions
|
||||
mkdir -p \
|
||||
${PULSE_SOCKET_DIR} \
|
||||
${USER_HOME:?}/.config/pulse
|
||||
chmod -R a+rw ${PULSE_SOCKET_DIR}
|
||||
chown -R ${PUID}:${PGID} ${USER_HOME:?}/.config/pulse
|
||||
|
||||
# Configure the palse audio socket
|
||||
sed -i "s|^; default-server.*$|default-server = ${PULSE_SERVER}|" /etc/pulse/client.conf
|
||||
sed -i "s|^load-module module-native-protocol-unix.*$|load-module module-native-protocol-unix socket=${PULSE_SOCKET_DIR}/pulse-socket auth-anonymous=1|" \
|
||||
/etc/pulse/default.pa
|
||||
|
||||
# Disable pulseaudio from respawning (https://unix.stackexchange.com/questions/204522/how-does-pulseaudio-start)
|
||||
sed -i 's|^; autospawn.*$|autospawn = no|' /etc/pulse/client.conf
|
||||
sed -i 's|^; daemon-binary.*$|daemon-binary = /bin/true|' /etc/pulse/client.conf
|
||||
|
||||
# Enable debug logging
|
||||
if [ "X${DEBUGGING:-}" == "X" ]; then
|
||||
sed -i 's|^; log-level.*$|log-level = debug|' /etc/pulse/daemon.conf
|
||||
fi
|
||||
fi
|
||||
chown -R ${USER} /etc/pulse
|
||||
|
||||
echo "DONE"
|
||||
213
overlay/etc/cont-init.d/60-configure_gpu_driver.sh
Normal file
@@ -0,0 +1,213 @@
|
||||
|
||||
# Fech NVIDIA GPU device (if one exists)
|
||||
if [ "${NVIDIA_VISIBLE_DEVICES:-}" = "all" ]; then
|
||||
export gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2> /dev/null | sed -n 2p)
|
||||
elif [ "${NVIDIA_VISIBLE_DEVICES:-}X" = "X" ]; then
|
||||
export gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2> /dev/null | sed -n 2p)
|
||||
else
|
||||
export gpu_select=$(nvidia-smi --format=csv --id=$(echo "$NVIDIA_VISIBLE_DEVICES" | cut -d ',' -f1) --query-gpu=uuid | sed -n 2p)
|
||||
if [ "${gpu_select:-}X" = "X" ]; then
|
||||
export gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2> /dev/null | sed -n 2p)
|
||||
fi
|
||||
fi
|
||||
|
||||
# NVIDIA Params
|
||||
export nvidia_pci_address="$(nvidia-smi --format=csv --query-gpu=pci.bus_id --id="${gpu_select:?}" 2> /dev/null | sed -n 2p | cut -d ':' -f2,3)"
|
||||
export nvidia_gpu_name=$(nvidia-smi --format=csv --query-gpu=name --id="${gpu_select:?}" 2> /dev/null | sed -n 2p)
|
||||
export nvidia_host_driver_version="$(nvidia-smi 2> /dev/null | grep NVIDIA-SMI | cut -d ' ' -f3)"
|
||||
|
||||
# Intel params
|
||||
# This figures out if it's an intel CPU with integrated GPU
|
||||
export intel_cpu_model="$(lscpu | grep 'Model name:' | grep -i intel | cut -d':' -f2 | xargs)"
|
||||
# We need to check if the user has an intel ARC GPU as well
|
||||
export intel_gpu_model="$(lspci | grep -i "VGA compatible controller: Intel" | cut -d':' -f3 | xargs)"
|
||||
|
||||
# AMD params
|
||||
export amd_cpu_model="$(lscpu | grep 'Model name:' | grep -i amd | cut -d':' -f2 | xargs)"
|
||||
export amd_gpu_model="$(lspci | grep -i vga | grep -i amd)"
|
||||
|
||||
function download_driver {
|
||||
mkdir -p "${USER_HOME:?}/Downloads"
|
||||
chown -R ${USER:?} "${USER_HOME:?}/Downloads"
|
||||
|
||||
if [[ ! -f "${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run" ]]; then
|
||||
echo "Downloading driver v${nvidia_host_driver_version:?}"
|
||||
wget -q --show-progress --progress=bar:force:noscroll \
|
||||
-O /tmp/NVIDIA.run \
|
||||
"http://download.nvidia.com/XFree86/Linux-x86_64/${nvidia_host_driver_version:?}/NVIDIA-Linux-x86_64-${nvidia_host_driver_version:?}.run"
|
||||
[[ $? -gt 0 ]] && echo "Error downloading driver. Exit!" && return 1
|
||||
|
||||
mv /tmp/NVIDIA.run "${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run"
|
||||
fi
|
||||
}
|
||||
|
||||
function install_nvidia_driver {
|
||||
# Check here if the currently installed version matches using nvidia-settings
|
||||
nvidia_settings_version=$(nvidia-settings --version 2> /dev/null | grep version | cut -d ' ' -f 4)
|
||||
if [ "${nvidia_settings_version:-}X" != "${nvidia_host_driver_version:-}X" ]; then
|
||||
# Download the driver (if it does not yet exist locally)
|
||||
download_driver
|
||||
|
||||
# if command -v pacman &> /dev/null; then
|
||||
# echo "Install NVIDIA vulkan utils" \
|
||||
# && pacman -Syu --noconfirm --needed \
|
||||
# lib32-nvidia-utils \
|
||||
# lib32-vulkan-icd-loader
|
||||
# nvidia-utils \
|
||||
# vulkan-icd-loader \
|
||||
# && echo
|
||||
# fi
|
||||
if (($(echo $nvidia_host_driver_version | cut -d '.' -f 1) > 500)); then
|
||||
echo "Installing NVIDIA driver v${nvidia_host_driver_version:?} to match what is running on the host"
|
||||
chmod +x "${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run"
|
||||
"${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run" \
|
||||
--silent \
|
||||
--accept-license \
|
||||
--skip-depmod \
|
||||
--skip-module-unload \
|
||||
--no-kernel-modules \
|
||||
--no-kernel-module-source \
|
||||
--install-compat32-libs \
|
||||
--no-nouveau-check \
|
||||
--no-nvidia-modprobe \
|
||||
--no-systemd \
|
||||
--no-distro-scripts \
|
||||
--no-rpms \
|
||||
--no-backup \
|
||||
--no-check-for-alternate-installs \
|
||||
--no-libglx-indirect \
|
||||
--no-install-libglvnd \
|
||||
> "${USER_HOME:?}/Downloads/nvidia_gpu_install.log" 2>&1
|
||||
else
|
||||
echo "Installing Legacy NVIDIA driver v${nvidia_host_driver_version:?} to match what is running on the host"
|
||||
chmod +x "${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run"
|
||||
"${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run" \
|
||||
--silent \
|
||||
--accept-license \
|
||||
--skip-depmod \
|
||||
--skip-module-unload \
|
||||
--no-kernel-module \
|
||||
--no-kernel-module-source \
|
||||
--install-compat32-libs \
|
||||
--no-nouveau-check \
|
||||
--no-nvidia-modprobe \
|
||||
--no-systemd \
|
||||
--no-distro-scripts \
|
||||
--no-rpms \
|
||||
--no-backup \
|
||||
--no-check-for-alternate-installs \
|
||||
--no-libglx-indirect \
|
||||
--no-install-libglvnd \
|
||||
> "${USER_HOME:?}/Downloads/nvidia_gpu_install.log" 2>&1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
function patch_nvidia_driver {
|
||||
# REF: https://github.com/keylase/nvidia-patch#docker-support
|
||||
if [ "${NVIDIA_PATCH_VERSION:-}X" != "X" ]; then
|
||||
# Don't fail boot if something goes wrong here. Set +e
|
||||
(
|
||||
set +e
|
||||
if [ ! -f "${USER_HOME:?}/Downloads/nvidia-patch.${NVIDIA_PATCH_VERSION:?}.sh" ]; then
|
||||
echo "Fetch NVIDIA NVENC patch"
|
||||
wget -q --show-progress --progress=bar:force:noscroll \
|
||||
-O "${USER_HOME:?}/Downloads/nvidia-patch.${NVIDIA_PATCH_VERSION:?}.sh" \
|
||||
"https://raw.githubusercontent.com/keylase/nvidia-patch/${NVIDIA_PATCH_VERSION:?}/patch.sh"
|
||||
fi
|
||||
if [ ! -f "${USER_HOME:?}/Downloads/nvidia-patch-fbc.${NVIDIA_PATCH_VERSION:?}.sh" ]; then
|
||||
echo "Fetch NVIDIA NvFBC patch"
|
||||
wget -q --show-progress --progress=bar:force:noscroll \
|
||||
-O "${USER_HOME:?}/Downloads/nvidia-patch-fbc.${NVIDIA_PATCH_VERSION:?}.sh" \
|
||||
"https://raw.githubusercontent.com/keylase/nvidia-patch/${NVIDIA_PATCH_VERSION:?}/patch-fbc.sh"
|
||||
fi
|
||||
chmod +x \
|
||||
"${USER_HOME:?}/Downloads/nvidia-patch.${NVIDIA_PATCH_VERSION:?}.sh" \
|
||||
"${USER_HOME:?}/Downloads/nvidia-patch-fbc.${NVIDIA_PATCH_VERSION:?}.sh"
|
||||
|
||||
echo "Install NVIDIA driver patches"
|
||||
echo "/patched-lib" > /etc/ld.so.conf.d/000-patched-lib.conf
|
||||
mkdir -p "/patched-lib"
|
||||
PATCH_OUTPUT_DIR="/patched-lib" "${USER_HOME:?}/Downloads/nvidia-patch.${NVIDIA_PATCH_VERSION:?}.sh"
|
||||
PATCH_OUTPUT_DIR="/patched-lib" "${USER_HOME:?}/Downloads/nvidia-patch-fbc.${NVIDIA_PATCH_VERSION:?}.sh"
|
||||
|
||||
pushd "/patched-lib" &> /dev/null || { echo "Error: Failed to push directory to /patched-lib"; exit 1; }
|
||||
for f in * ; do
|
||||
suffix="${f##*.so}"
|
||||
name="$(basename "$f" "$suffix")"
|
||||
[ -h "$name" ] || ln -sf "$f" "$name"
|
||||
[ -h "$name" ] || ln -sf "$f" "$name.1"
|
||||
done
|
||||
ldconfig
|
||||
popd &> /dev/null || { echo "Error: Failed to pop directory out of /patched-lib"; exit 1; }
|
||||
)
|
||||
else
|
||||
echo "Leaving NVIDIA driver stock without patching"
|
||||
fi
|
||||
}
|
||||
|
||||
function install_amd_gpu_driver {
|
||||
echo "Install AMD vulkan driver"
|
||||
if command -v pacman &> /dev/null; then
|
||||
pacman -Syu --noconfirm --needed \
|
||||
lib32-vulkan-icd-loader \
|
||||
lib32-vulkan-radeon \
|
||||
vulkan-icd-loader \
|
||||
vulkan-radeon
|
||||
# There is currently nothing to install inside the debian container. This already comes with the vulken drives that are required
|
||||
# elif command -v apt-get &> /dev/null; then
|
||||
# [[ "${APT_UPDATED:-false}" == 'false' ]] && apt-get update && export APT_UPDATED=true
|
||||
# apt-get install -y \
|
||||
# libvulkan1 \
|
||||
# libvulkan1:i386 \
|
||||
# mesa-vulkan-drivers \
|
||||
# mesa-vulkan-drivers:i386
|
||||
fi
|
||||
}
|
||||
|
||||
function install_intel_gpu_driver {
|
||||
echo "Install Intel vulkan driver"
|
||||
if command -v pacman &> /dev/null; then
|
||||
pacman -Syu --noconfirm --needed \
|
||||
lib32-vulkan-icd-loader \
|
||||
lib32-vulkan-intel \
|
||||
vulkan-icd-loader \
|
||||
vulkan-intel
|
||||
# There is currently nothing to install inside the debian container. This already comes with the vulken drives that are required
|
||||
# elif command -v apt-get &> /dev/null; then
|
||||
# [[ "${APT_UPDATED:-false}" == 'false' ]] && apt-get update && export APT_UPDATED=true
|
||||
# apt-get install -y \
|
||||
# libvulkan1 \
|
||||
# libvulkan1:i386 \
|
||||
# mesa-vulkan-drivers \
|
||||
# mesa-vulkan-drivers:i386
|
||||
fi
|
||||
}
|
||||
|
||||
# Intel Arc GPU or Intel CPU with possible iGPU
|
||||
if [ "${intel_gpu_model:-}X" != "X" ]; then
|
||||
echo "**** Found Intel device '${intel_gpu_model:?}' ****"
|
||||
install_intel_gpu_driver
|
||||
elif [ "${intel_cpu_model:-}X" != "X" ]; then
|
||||
echo "**** Found Intel device '${intel_cpu_model:?}' ****"
|
||||
install_intel_gpu_driver
|
||||
else
|
||||
echo "**** No Intel device found ****"
|
||||
fi
|
||||
# AMD GPU
|
||||
if [ "${amd_gpu_model:-}X" != "X" ]; then
|
||||
echo "**** Found AMD device '${amd_gpu_model:?}' ****"
|
||||
install_amd_gpu_driver
|
||||
else
|
||||
echo "**** No AMD device found ****"
|
||||
fi
|
||||
# NVIDIA GPU
|
||||
if [ "${nvidia_pci_address:-}X" != "X" ]; then
|
||||
echo "**** Found NVIDIA device '${nvidia_gpu_name:?}' ****"
|
||||
install_nvidia_driver
|
||||
patch_nvidia_driver
|
||||
else
|
||||
echo "**** No NVIDIA device found ****"
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
22
overlay/etc/cont-init.d/70-configure_desktop.sh
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
echo "**** Configure Desktop ****"
|
||||
|
||||
if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
|
||||
echo "Enable Desktop service."
|
||||
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/desktop.ini
|
||||
else
|
||||
echo "Desktop service not available when container is run in 'secondary' mode."
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/desktop.ini
|
||||
fi
|
||||
|
||||
# Setup home directory
|
||||
if [[ ! -f /tmp/.home-directory-template-updated ]]; then
|
||||
echo "Ensure home directory template is owned by the default user."
|
||||
chown -R ${PUID}:${PGID} /templates/home_directory_template
|
||||
echo "Installing default home directory template"
|
||||
mkdir -p "${USER_HOME:?}"
|
||||
rsync -aq /templates/home_directory_template/ "${USER_HOME:?}"/
|
||||
touch /tmp/.home-directory-template-updated
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
129
overlay/etc/cont-init.d/70-configure_xorg.sh
Normal file
@@ -0,0 +1,129 @@
|
||||
|
||||
# Fech NVIDIA GPU device (if one exists)
|
||||
if [ "${NVIDIA_VISIBLE_DEVICES:-}" == "all" ]; then
|
||||
export gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2> /dev/null | sed -n 2p)
|
||||
elif [ -z "${NVIDIA_VISIBLE_DEVICES:-}" ]; then
|
||||
export gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2> /dev/null | sed -n 2p)
|
||||
else
|
||||
export gpu_select=$(nvidia-smi --format=csv --id=$(echo "$NVIDIA_VISIBLE_DEVICES" | cut -d ',' -f1) --query-gpu=uuid | sed -n 2p)
|
||||
if [ -z "$gpu_select" ]; then
|
||||
export gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2> /dev/null | sed -n 2p)
|
||||
fi
|
||||
fi
|
||||
|
||||
export nvidia_gpu_hex_id=$(nvidia-smi --format=csv --query-gpu=pci.bus_id --id="${gpu_select}" 2> /dev/null | sed -n 2p)
|
||||
|
||||
export monitor_connected=$(cat /sys/class/drm/card*/status | awk '/^connected/ { print $1; }' | head -n1)
|
||||
|
||||
# Fech current configuration (if modified in UI)
|
||||
if [ -f "${USER_HOME}/.config/xfce4/xfconf/xfce-perchannel-xml/displays.xml" ]; then
|
||||
new_display_sizew=$(cat ${USER_HOME}/.config/xfce4/xfconf/xfce-perchannel-xml/displays.xml | grep Resolution | head -n1 | grep -oP '(?<=value=").*?(?=")' | cut -d'x' -f1)
|
||||
new_display_sizeh=$(cat ${USER_HOME}/.config/xfce4/xfconf/xfce-perchannel-xml/displays.xml | grep Resolution | head -n1 | grep -oP '(?<=value=").*?(?=")' | cut -d'x' -f2)
|
||||
new_display_refresh=$(cat ${USER_HOME}/.config/xfce4/xfconf/xfce-perchannel-xml/displays.xml | grep RefreshRate | head -n1 | grep -oP '(?<=value=").*?(?=")' | cut -d'x' -f2)
|
||||
if [ "${new_display_sizew}x" != "x" ] && [ "${new_display_sizeh}x" != "x" ] && [ "${new_display_refresh}x" != "x" ]; then
|
||||
export DISPLAY_SIZEW="${new_display_sizew}"
|
||||
export DISPLAY_SIZEH="${new_display_sizeh}"
|
||||
# Round refresh rate to closest multiple of 60
|
||||
export DISPLAY_REFRESH="$(echo ${new_display_refresh} | awk '{rounded = int(($1 + 30) / 60) * 60; if (rounded < 30) rounded += 60; print rounded}')"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Configure a NVIDIA X11 config
|
||||
function configure_nvidia_x_server {
|
||||
echo "Configuring X11 with GPU ID: '${gpu_select}'"
|
||||
nvidia_gpu_hex_id=$(nvidia-smi --format=csv --query-gpu=pci.bus_id --id="${gpu_select}" 2> /dev/null | sed -n 2p)
|
||||
IFS=":." ARR_ID=(${nvidia_gpu_hex_id})
|
||||
unset IFS
|
||||
bus_id=PCI:$((16#${ARR_ID[1]})):$((16#${ARR_ID[2]})):$((16#${ARR_ID[3]}))
|
||||
echo "Configuring X11 with PCI bus ID: '${bus_id}'"
|
||||
export MODELINE=$(cvt -r "${DISPLAY_SIZEW}" "${DISPLAY_SIZEH}" "${DISPLAY_REFRESH}" | sed -n 2p)
|
||||
echo "Writing X11 config with ${MODELINE}"
|
||||
connected_monitor="--use-display-device=None"
|
||||
if [[ "X${DISPLAY_VIDEO_PORT:-}" != "X" ]]; then
|
||||
connected_monitor="--connected-monitor=${DISPLAY_VIDEO_PORT:?}"
|
||||
fi
|
||||
nvidia-xconfig --virtual="${DISPLAY_SIZEW:?}x${DISPLAY_SIZEH:?}" --depth="${DISPLAY_CDEPTH:?}" --mode=$(echo "${MODELINE:?}" | awk '{print $2}' | tr -d '"') --allow-empty-initial-configuration --no-probe-all-gpus --busid="${bus_id:?}" --no-multigpu --no-sli --no-base-mosaic --only-one-x-screen ${connected_monitor:?}
|
||||
sed -i '/Driver\s\+"nvidia"/a\ Option "ModeValidation" "NoMaxPClkCheck, NoEdidMaxPClkCheck, NoMaxSizeCheck, NoHorizSyncCheck, NoVertRefreshCheck, NoVirtualSizeCheck, NoTotalSizeCheck, NoDualLinkDVICheck, NoDisplayPortBandwidthCheck, AllowNon3DVisionModes, AllowNonHDMI3DModes, AllowNonEdidModes, NoEdidHDMI2Check, AllowDpInterlaced"\n Option "HardDPMS" "False"' /etc/X11/xorg.conf
|
||||
sed -i '/Section\s\+"Monitor"/a\ '"${MODELINE}" /etc/X11/xorg.conf
|
||||
# Prevent interference between GPUs
|
||||
echo -e "Section \"ServerFlags\"\n Option \"AutoAddGPU\" \"false\"\nEndSection" | tee -a /etc/X11/xorg.conf > /dev/null
|
||||
# Configure primary GPU
|
||||
sed -i '/Driver\s\+"nvidia"/a\ Option "AllowEmptyInitialConfiguration"\n Option "PrimaryGPU" "yes"' /usr/share/X11/xorg.conf.d/nvidia-drm-outputclass.conf
|
||||
}
|
||||
|
||||
# Allow anybody for running x server
|
||||
function configure_x_server {
|
||||
# Configure x to be run by anyone
|
||||
if [[ ! -f /etc/X11/Xwrapper.config ]]; then
|
||||
echo "Create Xwrapper.config"
|
||||
echo 'allowed_users=anybody' > /etc/X11/Xwrapper.config
|
||||
echo 'needs_root_rights=yes' >> /etc/X11/Xwrapper.config
|
||||
elif grep -Fxq "allowed_users=console" /etc/X11/Xwrapper.config; then
|
||||
echo "Configure Xwrapper.config"
|
||||
sed -i "s/allowed_users=console/allowed_users=anybody/" /etc/X11/Xwrapper.config
|
||||
echo 'needs_root_rights=yes' >> /etc/X11/Xwrapper.config
|
||||
fi
|
||||
|
||||
# Remove previous Xorg config
|
||||
rm -f /etc/X11/xorg.conf
|
||||
|
||||
# Ensure the X socket path exists
|
||||
mkdir -p ${XORG_SOCKET_DIR:?}
|
||||
|
||||
# Clear out old lock files
|
||||
display_file=${XORG_SOCKET_DIR}/X${DISPLAY#:}
|
||||
if [ -S ${display_file} ]; then
|
||||
echo "Removing ${display_file} before starting"
|
||||
rm -f /tmp/.X${DISPLAY#:}-lock
|
||||
rm ${display_file}
|
||||
fi
|
||||
|
||||
# Ensure X-windows session path is owned by root
|
||||
mkdir -p /tmp/.ICE-unix
|
||||
chown root:root /tmp/.ICE-unix/
|
||||
chmod 1777 /tmp/.ICE-unix/
|
||||
|
||||
# Check if this container is being run as a secondary instance
|
||||
if [ "${MODE}" == "p" ] | [ "${MODE}" == "primary" ]; then
|
||||
echo "Configure container as primary the X server"
|
||||
# Enable supervisord script
|
||||
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/xorg.ini
|
||||
elif [ "${MODE}" == "fb" ] | [ "${MODE}" == "framebuffer" ]; then
|
||||
echo "Configure container to use a virtual framebuffer as the X server"
|
||||
# Disable xorg supervisord script
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/xorg.ini
|
||||
# Enable xvfb supervisord script
|
||||
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/xvfb.ini
|
||||
else
|
||||
echo "Configure container with no X server"
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/xorg.ini
|
||||
fi
|
||||
|
||||
# Enable KB/Mouse input capture with Xorg if configured
|
||||
if [ ${ENABLE_EVDEV_INPUTS:-} = "true" ]; then
|
||||
echo "Enabling evdev input class on pointers, keyboards, touchpads, touch screens, etc."
|
||||
cp -fv /usr/share/X11/xorg.conf.d/10-evdev.conf /etc/X11/xorg.conf.d/10-evdev.conf
|
||||
else
|
||||
echo "Leaving evdev inputs disabled"
|
||||
fi
|
||||
|
||||
# Configure dummy config if no monitor is connected (not applicable to NVIDIA)
|
||||
if [[ "X${monitor_connected}" == "X" ]]; then
|
||||
echo "No monitors connected. Installing dummy xorg.conf"
|
||||
# Use a dummy display input
|
||||
cp -fv /templates/xorg/xorg.dummy.conf /etc/X11/xorg.conf
|
||||
fi
|
||||
}
|
||||
|
||||
if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
|
||||
if [[ -z ${nvidia_gpu_hex_id} ]]; then
|
||||
echo "**** Generate default xorg.conf ****";
|
||||
configure_x_server
|
||||
else
|
||||
echo "**** Generate NVIDIA xorg.conf ****";
|
||||
configure_x_server
|
||||
configure_nvidia_x_server
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
13
overlay/etc/cont-init.d/80-configure_flatpak.sh
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
echo "**** Configure Flatpak ****"
|
||||
|
||||
if [ "X${NVIDIA_VISIBLE_DEVICES:-}" != "X" ]; then
|
||||
# Fix some flatpak quirks (not sure what is happening here) for NVIDIA containers
|
||||
mount -t proc none /proc
|
||||
flatpak list
|
||||
echo "Flatpak configured for running inside a Docker container"
|
||||
else
|
||||
echo "Flatpak already configured for running inside a Docker container"
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
48
overlay/etc/cont-init.d/90-configure_neko.sh
Normal file
@@ -0,0 +1,48 @@
|
||||
|
||||
echo "**** Configure Neko ****"
|
||||
# REF: https://neko.m1k1o.net/#/getting-started/configuration
|
||||
|
||||
if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
|
||||
if [ ${WEB_UI_MODE} = "neko" ]; then
|
||||
echo "Enable Neko server"
|
||||
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/neko.ini
|
||||
|
||||
# Make directories for neko
|
||||
mkdir -p /var/log/neko
|
||||
chmod 1777 /var/log/neko
|
||||
chown ${USER} /var/log/neko
|
||||
|
||||
# Configure nat1to1 if it is not already set
|
||||
if [[ -z ${NEKO_NAT1TO1} ]]; then
|
||||
export NEKO_NAT1TO1=$(ip route get 1 | awk '{print $(NF-2);exit}')
|
||||
echo "Setting NEKO_NAT1TO1=${NEKO_NAT1TO1}"
|
||||
else
|
||||
echo "User provided setting NEKO_NAT1TO1=${NEKO_NAT1TO1}"
|
||||
fi
|
||||
|
||||
# Configure hardware acceleration if it is not already set
|
||||
# if [[ -z ${NEKO_HWENC} ]]; then
|
||||
# # Enable VAAPI if device available
|
||||
# if [[ ! -z $(stat -c "%g" /dev/dri/render* | tail -n 1) ]]; then
|
||||
# echo "Setting Neko to use VAAPI encoder"
|
||||
# export NEKO_HWENC="VAAPI"
|
||||
# # Check for vp8 vaapi encoder
|
||||
# echo "Setting Neko to use 264 encoding"
|
||||
# # export NEKO_VP8="false"
|
||||
# # export NEKO_VP9="false"
|
||||
# export NEKO_H264="true"
|
||||
# fi
|
||||
# fi
|
||||
|
||||
# Configure screen size if it is not already set
|
||||
if [[ -z ${NEKO_SCREEN} ]]; then
|
||||
export NEKO_SCREEN="${DISPLAY_SIZEW}x${DISPLAY_SIZEH}@${DISPLAY_REFRESH}"
|
||||
fi
|
||||
else
|
||||
echo "Disable Neko server"
|
||||
fi
|
||||
else
|
||||
echo "Neko server not available when container is run in 'secondary' mode"
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
35
overlay/etc/cont-init.d/90-configure_steam.sh
Normal file
@@ -0,0 +1,35 @@
|
||||
|
||||
echo "**** Configure Steam ****"
|
||||
|
||||
steam_autostart_desktop="$(cat <<EOF
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
Type=Application
|
||||
Name=Steam
|
||||
Comment=Launch steam on login
|
||||
Exec=/usr/games/steam %U ${STEAM_ARGS:-}
|
||||
Icon=steam
|
||||
OnlyShowIn=XFCE;
|
||||
RunHook=0
|
||||
StartupNotify=false
|
||||
Terminal=false
|
||||
Hidden=false
|
||||
EOF
|
||||
)"
|
||||
|
||||
if [ "${ENABLE_STEAM:-}" = "true" ]; then
|
||||
if [ "${MODE}" == "s" ] | [ "${MODE}" == "secondary" ]; then
|
||||
echo "Enable Steam supervisor.d service"
|
||||
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/steam.ini
|
||||
else
|
||||
echo "Enable Steam auto-start script"
|
||||
mkdir -p "${USER_HOME:?}/.config/autostart"
|
||||
echo "${steam_autostart_desktop:?}" > "${USER_HOME:?}/.config/autostart/Steam.desktop"
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/steam.ini
|
||||
fi
|
||||
else
|
||||
echo "Disable Steam service"
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/steam.ini
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
15
overlay/etc/cont-init.d/90-configure_sunshine.sh
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
echo "**** Configure Sunshine ****"
|
||||
|
||||
if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
|
||||
if [ "${ENABLE_SUNSHINE:-}" = "true" ]; then
|
||||
echo "Enable Sunshine server"
|
||||
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/sunshine.ini
|
||||
else
|
||||
echo "Disable Sunshine server"
|
||||
fi
|
||||
else
|
||||
echo "Sunshine server not available when container is run in 'secondary' mode"
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
51
overlay/etc/cont-init.d/90-configure_vnc.sh
Normal file
@@ -0,0 +1,51 @@
|
||||
|
||||
echo "**** Configure VNC ****"
|
||||
|
||||
function get_next_unused_port() {
|
||||
local __start_port=${1}
|
||||
local __start_port=$((__start_port+1))
|
||||
local __netstat_report=$(netstat -atulnp 2> /dev/null)
|
||||
for __check_port in $(seq ${__start_port} 65000); do
|
||||
[[ -z $(echo "${__netstat_report}" | grep ${__check_port}) ]] && break;
|
||||
done
|
||||
echo ${__check_port}
|
||||
}
|
||||
|
||||
# Configure random ports for VNC service, pulseaudio socket, noVNC service and audio transport websocket
|
||||
# Note: Ports 32035-32248 are unallocated port ranges. We should be able to find something in here that we can use
|
||||
# REF: https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?&page=130
|
||||
DYNAMIC_PORT_VNC=$(get_next_unused_port 32035)
|
||||
export PORT_VNC=${PORT_VNC:-$DYNAMIC_PORT_VNC}
|
||||
echo "Configure VNC service port '${PORT_VNC}'"
|
||||
DYNAMIC_PORT_AUDIO_STREAM=$(get_next_unused_port ${DYNAMIC_PORT_VNC})
|
||||
export PORT_AUDIO_STREAM=${PORT_AUDIO_STREAM:-$DYNAMIC_PORT_AUDIO_STREAM}
|
||||
echo "Configure pulseaudio encoded stream port '${PORT_AUDIO_STREAM}'"
|
||||
|
||||
if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
|
||||
|
||||
if [ "${WEB_UI_MODE:-}" = "vnc" ]; then
|
||||
echo "Enable VNC server"
|
||||
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/vnc.ini
|
||||
|
||||
# TODO: Remove this... Always enable VNC audio
|
||||
if [[ "${ENABLE_VNC_AUDIO}" == "true" ]]; then
|
||||
# Enable supervisord script
|
||||
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/vnc-audio.ini
|
||||
else
|
||||
echo "Disable audio stream"
|
||||
echo "Disable audio websock"
|
||||
# Disable supervisord script
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/vnc-audio.ini
|
||||
fi
|
||||
else
|
||||
echo "Disable VNC server"
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/vnc.ini
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/vnc-audio.ini
|
||||
fi
|
||||
else
|
||||
echo "VNC server not available when container is run in 'secondary' mode"
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/vnc.ini
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/vnc-audio.ini
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
34
overlay/etc/cont-init.d/95-setup_wol.sh
Normal file
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env bash
|
||||
###
|
||||
# File: 10-setup_user.sh
|
||||
# Project: cont-init.d
|
||||
# File Created: Tuesday, 5th September 2023 6:15:12 pm
|
||||
# Author: Josh.5 (jsunnex@gmail.com)
|
||||
# -----
|
||||
# Last Modified: Tuesday, 5th September 2023 6:39:32 pm
|
||||
# Modified By: Josh.5 (jsunnex@gmail.com)
|
||||
###
|
||||
|
||||
echo "**** Configure WoL Manager ****"
|
||||
|
||||
if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
|
||||
if [ "${ENABLE_WOL_POWER_MANAGER:-}" = "true" ]; then
|
||||
if [ -f "/tmp/.wol-monitor" ]; then
|
||||
echo "Container started in WoL Manager mode. Disabling all other services."
|
||||
for init_config in /etc/supervisor.d/*.ini ; do
|
||||
init_config_basename=$(basename "${init_config:?}")
|
||||
init_name="${init_config_basename%.*}"
|
||||
[ "${init_name:?}" = "wol-power-manager" ] && continue
|
||||
echo " - Disable ${init_name:?}"
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' "${init_config:?}"
|
||||
done
|
||||
fi
|
||||
echo "Enable WoL Manager service."
|
||||
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/wol-power-manager.ini
|
||||
else
|
||||
echo "Disable WoL Manager service."
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/wol-power-manager.ini
|
||||
fi
|
||||
else
|
||||
echo "WoL Manager service not available when container is run in 'secondary' mode."
|
||||
fi
|
||||
8
overlay/etc/docker/daemon.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"runtimes": {
|
||||
"nvidia": {
|
||||
"path": "/usr/bin/nvidia-container-runtime",
|
||||
"runtimeArgs": []
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
Version=0.9.4
|
||||
Type=Application
|
||||
Name=Steam
|
||||
Comment=launch steam on login
|
||||
Exec=/usr/games/steam %U
|
||||
Icon=steam
|
||||
OnlyShowIn=XFCE;
|
||||
RunHook=0
|
||||
StartupNotify=false
|
||||
Terminal=false
|
||||
Hidden=false
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
# Hide application from menu
|
||||
[Desktop Entry]
|
||||
Name=X11VNC Server
|
||||
Comment=Share this desktop by VNC
|
||||
Exec=x11vnc -gui tray=setpass -rfbport PROMPT -bg -o %%HOME/.x11vnc.log.%%VNCDISPLAY
|
||||
Icon=computer
|
||||
Terminal=false
|
||||
Type=Application
|
||||
StartupNotify=false
|
||||
#StartupWMClass=x11vnc_port_prompt
|
||||
Categories=Network;RemoteAccess;
|
||||
Hidden=true
|
||||
16
overlay/etc/supervisor.d/dbus.ini
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
[program:dbus]
|
||||
priority=10
|
||||
autostart=true
|
||||
autorestart=true
|
||||
directory=/
|
||||
user=%(ENV_USER)s
|
||||
command=dbus-daemon --config-file=/usr/share/dbus-1/system.conf --nofork --nopidfile
|
||||
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s"
|
||||
stopsignal=INT
|
||||
stdout_logfile=/var/log/supervisor/dbus.log
|
||||
stdout_logfile_maxbytes=10MB
|
||||
stdout_logfile_backups=7
|
||||
stderr_logfile=/var/log/supervisor/dbus.err.log
|
||||
stderr_logfile_maxbytes=10MB
|
||||
stderr_logfile_backups=7
|
||||
16
overlay/etc/supervisor.d/desktop.ini
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
[program:desktop]
|
||||
priority=50
|
||||
autostart=true
|
||||
autorestart=true
|
||||
user=%(ENV_USER)s
|
||||
directory=/home/%(ENV_USER)s
|
||||
command=/usr/bin/start-desktop.sh
|
||||
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s",XDG_RUNTIME_DIR="%(ENV_XDG_RUNTIME_DIR)s"
|
||||
stopsignal=INT
|
||||
stdout_logfile=/home/%(ENV_USER)s/.cache/log/desktop.log
|
||||
stdout_logfile_maxbytes=10MB
|
||||
stdout_logfile_backups=7
|
||||
stderr_logfile=/home/%(ENV_USER)s/.cache/log/desktop.err.log
|
||||
stderr_logfile_maxbytes=10MB
|
||||
stderr_logfile_backups=7
|
||||
19
overlay/etc/supervisor.d/neko.ini
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
[program:neko]
|
||||
priority=30
|
||||
autostart=false
|
||||
autorestart=true
|
||||
user=%(ENV_USER)s
|
||||
# /usr/bin/neko serve --static "/var/www" --display ${DISPLAY} --bind :${PORT_NOVNC_WEB}
|
||||
# /usr/bin/neko serve --static "/var/www" --display ${DISPLAY} --bind :${PORT_NOVNC_WEB} --nat1to1 $(ip route get 1 | awk '{print $(NF-2);exit}') --screen 1280x720@30 --hwenc VAAPI --h264
|
||||
# /usr/bin/neko serve --static "/var/www" --display ${DISPLAY} --bind :${PORT_NOVNC_WEB} --nat1to1 $(ip route get 1 | awk '{print $(NF-2);exit}') --screen 1280x720@30 --vp8
|
||||
command=/usr/bin/neko serve --static "/var/www" --display %(ENV_DISPLAY)s --bind :%(ENV_PORT_NOVNC_WEB)s
|
||||
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s",XDG_RUNTIME_DIR="%(ENV_XDG_RUNTIME_DIR)s"
|
||||
stopsignal=INT
|
||||
stopwaitsecs=5
|
||||
stdout_logfile=/home/%(ENV_USER)s/.cache/log/neko.log
|
||||
stdout_logfile_maxbytes=10MB
|
||||
stdout_logfile_backups=7
|
||||
stderr_logfile=/home/%(ENV_USER)s/.cache/log/neko.err.log
|
||||
stderr_logfile_maxbytes=10MB
|
||||
stderr_logfile_backups=7
|
||||
15
overlay/etc/supervisor.d/pulseaudio.ini
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
[program:pulseaudio]
|
||||
priority=30
|
||||
autostart=true
|
||||
autorestart=true
|
||||
directory=/
|
||||
user=%(ENV_USER)s
|
||||
command=/usr/bin/start-pulseaudio.sh
|
||||
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s"
|
||||
stopsignal=INT
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/home/%(ENV_USER)s/.cache/log/pulseaudio.err.log
|
||||
stderr_logfile_maxbytes=2MB
|
||||
stderr_logfile_backups=7
|
||||
21
overlay/etc/supervisor.d/steam.ini
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
# Optionally launch directly to steam big picture (disabled by default)
|
||||
[program:steam]
|
||||
priority=50
|
||||
autostart=false
|
||||
autorestart=true
|
||||
# Retry a restart a few times.
|
||||
# This allows this container to start up before X is ready and restart the process until it becomes available.
|
||||
# Each restart will have a small delay of a few seconds. So 50 attempts should be a few mins.
|
||||
startretries=50
|
||||
user=%(ENV_USER)s
|
||||
directory=/home/%(ENV_USER)s
|
||||
command=/usr/games/steam %(ENV_STEAM_ARGS)s
|
||||
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
|
||||
stopsignal=INT
|
||||
stdout_logfile=/home/%(ENV_USER)s/.cache/log/steam.log
|
||||
stdout_logfile_maxbytes=10MB
|
||||
stdout_logfile_backups=7
|
||||
stderr_logfile=/home/%(ENV_USER)s/.cache/log/steam.err.log
|
||||
stderr_logfile_maxbytes=10MB
|
||||
stderr_logfile_backups=7
|
||||
20
overlay/etc/supervisor.d/sunshine.ini
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
[program:sunshine]
|
||||
priority=50
|
||||
autostart=false
|
||||
autorestart=true
|
||||
# Retry a restart a few times.
|
||||
# The start-sunshine.sh script has a section that will wait for the
|
||||
# X server to become available before executing sunshine. However, this will time out after 30 seconds.
|
||||
startretries=10
|
||||
user=%(ENV_USER)s
|
||||
directory=/home/%(ENV_USER)s
|
||||
command=/usr/bin/start-sunshine.sh
|
||||
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s",XDG_RUNTIME_DIR="%(ENV_XDG_RUNTIME_DIR)s"
|
||||
stopsignal=INT
|
||||
stdout_logfile=/home/%(ENV_USER)s/.cache/log/sunshine.log
|
||||
stdout_logfile_maxbytes=10MB
|
||||
stdout_logfile_backups=7
|
||||
stderr_logfile=/home/%(ENV_USER)s/.cache/log/sunshine.err.log
|
||||
stderr_logfile_maxbytes=10MB
|
||||
stderr_logfile_backups=7
|
||||
15
overlay/etc/supervisor.d/udev.ini
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
[program:udev]
|
||||
priority=10
|
||||
autostart=false
|
||||
autorestart=true
|
||||
user=root
|
||||
directory=/
|
||||
command=/usr/bin/start-udev.sh
|
||||
stopsignal=INT
|
||||
stdout_logfile=/var/log/supervisor/udev.log
|
||||
stdout_logfile_maxbytes=10MB
|
||||
stdout_logfile_backups=7
|
||||
stderr_logfile=/var/log/supervisor/udev.err.log
|
||||
stderr_logfile_maxbytes=10MB
|
||||
stderr_logfile_backups=7
|
||||
14
overlay/etc/supervisor.d/vnc-audio.ini
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
[program:audiostream]
|
||||
priority=30
|
||||
autostart=false
|
||||
autorestart=true
|
||||
user=%(ENV_USER)s
|
||||
command=tcpserver 127.0.0.1 %(ENV_PORT_AUDIO_STREAM)s gst-launch-1.0 -q pulsesrc server=%(ENV_PULSE_SOCKET_DIR)s/pulse-socket ! audio/x-raw, channels=2, rate=24000 ! cutter ! opusenc ! webmmux ! fdsink fd=1
|
||||
stopsignal=INT
|
||||
stdout_logfile=/home/%(ENV_USER)s/.cache/log/audiostream.log
|
||||
stdout_logfile_maxbytes=10MB
|
||||
stdout_logfile_backups=7
|
||||
stderr_logfile=/home/%(ENV_USER)s/.cache/log/audiostream.err.log
|
||||
stderr_logfile_maxbytes=10MB
|
||||
stderr_logfile_backups=7
|
||||
30
overlay/etc/supervisor.d/vnc.ini
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
[program:x11vnc]
|
||||
priority=30
|
||||
autostart=false
|
||||
autorestart=true
|
||||
user=root
|
||||
command=/usr/bin/start-x11vnc.sh
|
||||
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s",PORT_VNC="%(ENV_PORT_VNC)s"
|
||||
stopsignal=INT
|
||||
stdout_logfile=/home/%(ENV_USER)s/.cache/log/x11vnc.log
|
||||
stdout_logfile_maxbytes=10MB
|
||||
stdout_logfile_backups=7
|
||||
stderr_logfile=/home/%(ENV_USER)s/.cache/log/x11vnc.err.log
|
||||
stderr_logfile_maxbytes=10MB
|
||||
stderr_logfile_backups=7
|
||||
|
||||
[program:frontend]
|
||||
priority=30
|
||||
autostart=false
|
||||
autorestart=true
|
||||
user=root
|
||||
command=/opt/frontend/utils/run.sh --web-port %(ENV_PORT_NOVNC_WEB)s --remote-host localhost --vnc-port %(ENV_PORT_VNC)s --audio-port %(ENV_PORT_AUDIO_STREAM)s
|
||||
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s"
|
||||
stopsignal=INT
|
||||
stdout_logfile=/home/%(ENV_USER)s/.cache/log/novnc.log
|
||||
stdout_logfile_maxbytes=10MB
|
||||
stdout_logfile_backups=7
|
||||
stderr_logfile=/home/%(ENV_USER)s/.cache/log/novnc.err.log
|
||||
stderr_logfile_maxbytes=10MB
|
||||
stderr_logfile_backups=7
|
||||
15
overlay/etc/supervisor.d/wol-power-manager.ini
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
[program:wol-power-manager]
|
||||
priority=60
|
||||
autostart=false
|
||||
autorestart=true
|
||||
user=root
|
||||
command=/usr/bin/steam-headless-wol-power-manager
|
||||
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s"
|
||||
stopsignal=INT
|
||||
stdout_logfile=/home/%(ENV_USER)s/.cache/log/wol-power-manager.log
|
||||
stdout_logfile_maxbytes=10MB
|
||||
stdout_logfile_backups=7
|
||||
stderr_logfile=/home/%(ENV_USER)s/.cache/log/wol-power-manager.err.log
|
||||
stderr_logfile_maxbytes=10MB
|
||||
stderr_logfile_backups=7
|
||||
15
overlay/etc/supervisor.d/xorg.ini
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
[program:xorg]
|
||||
priority=20
|
||||
autostart=false
|
||||
autorestart=true
|
||||
user=root
|
||||
command=/usr/bin/start-xorg.sh
|
||||
environment=DISPLAY="%(ENV_DISPLAY)s",XDG_RUNTIME_DIR="/tmp/runtime-root"
|
||||
stopsignal=INT
|
||||
stdout_logfile=/home/%(ENV_USER)s/.cache/log/xorg.log
|
||||
stdout_logfile_maxbytes=10MB
|
||||
stdout_logfile_backups=7
|
||||
stderr_logfile=/home/%(ENV_USER)s/.cache/log/xorg.err.log
|
||||
stderr_logfile_maxbytes=10MB
|
||||
stderr_logfile_backups=7
|
||||
13
overlay/etc/supervisor.d/xvfb.ini
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
[program:xvfb]
|
||||
priority=20
|
||||
autostart=false
|
||||
autorestart=true
|
||||
user=root
|
||||
command=/usr/bin/Xvfb %(ENV_DISPLAY)s -screen 0 "%(ENV_DISPLAY_SIZEW)sx%(ENV_DISPLAY_SIZEH)sx24"
|
||||
environment=DISPLAY="%(ENV_DISPLAY)s"
|
||||
stopsignal=INT
|
||||
stdout_logfile_maxbytes=10MB
|
||||
stdout_logfile_backups=7
|
||||
stderr_logfile_maxbytes=10MB
|
||||
stderr_logfile_backups=7
|
||||
@@ -1,130 +0,0 @@
|
||||
[supervisord]
|
||||
user=root
|
||||
nodaemon=true
|
||||
|
||||
[program:ssh]
|
||||
autostart=true
|
||||
priority=10
|
||||
directory=/
|
||||
command=/usr/sbin/sshd -D
|
||||
user=root
|
||||
autorestart=true
|
||||
stopsignal=QUIT
|
||||
|
||||
[program:dbus]
|
||||
autostart=true
|
||||
priority=10
|
||||
directory=/
|
||||
command=dbus-daemon --config-file=/usr/share/dbus-1/system.conf --nofork --nopidfile
|
||||
user=%(ENV_USER)s
|
||||
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s"
|
||||
autorestart=true
|
||||
stopsignal=QUIT
|
||||
|
||||
[program:pulseaudio]
|
||||
autostart=true
|
||||
priority=10
|
||||
directory=/
|
||||
command=/usr/bin/pulseaudio -vvvv --disallow-module-loading --disallow-exit --exit-idle-time=-1
|
||||
user=%(ENV_USER)s
|
||||
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s"
|
||||
autorestart=true
|
||||
stopsignal=QUIT
|
||||
stdout_logfile=/home/%(ENV_USER)s/.cache/log/pulseaudio.log
|
||||
stderr_logfile=/home/%(ENV_USER)s/.cache/log/pulseaudio.err
|
||||
|
||||
[program:audiostream]
|
||||
autostart=true
|
||||
priority=10
|
||||
command=tcpserver localhost 5901 gst-launch-1.0 -q pulsesrc server=/tmp/pulseaudio.socket ! audio/x-raw, channels=2, rate=24000 ! cutter ! opusenc ! webmmux ! fdsink fd=1
|
||||
autorestart=true
|
||||
stopsignal=QUIT
|
||||
stdout_logfile=/home/%(ENV_USER)s/.cache/log/audiostream.log
|
||||
stderr_logfile=/home/%(ENV_USER)s/.cache/log/audiostream.err
|
||||
|
||||
[program:audiowebsock]
|
||||
autostart=true
|
||||
priority=10
|
||||
command=/usr/local/bin/websockify 32123 localhost:5901
|
||||
autorestart=true
|
||||
stopsignal=QUIT
|
||||
stdout_logfile=/home/%(ENV_USER)s/.cache/log/audiowebsock.log
|
||||
stderr_logfile=/home/%(ENV_USER)s/.cache/log/audiowebsock.err
|
||||
|
||||
[program:xorg]
|
||||
autostart=true
|
||||
priority=20
|
||||
directory=/
|
||||
command=/usr/bin/Xorg vt7 -novtswitch -sharevts -dpi "%(ENV_DISPLAY_DPI)s" +extension "MIT-SHM" %(ENV_DISPLAY)s
|
||||
#command=/usr/bin/Xorg -novtswitch -sharevts -dpi "%(ENV_DISPLAY_DPI)s" +extension "MIT-SHM" "%(ENV_DISPLAY)s"
|
||||
user=%(ENV_USER)s
|
||||
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s",XDG_RUNTIME_DIR="/tmp/xdg",RUNLEVEL="3"
|
||||
autorestart=true
|
||||
stopsignal=QUIT
|
||||
stdout_logfile=/home/%(ENV_USER)s/.cache/log/xorg.log
|
||||
stderr_logfile=/home/%(ENV_USER)s/.cache/log/xorg.err
|
||||
|
||||
# Dont use xvfb as it does not work with nvidia X11 configuration
|
||||
# [program:xvfb]
|
||||
# autostart=false
|
||||
# priority=20
|
||||
# directory=/
|
||||
# command=/usr/bin/Xvfb %(ENV_DISPLAY)s -screen 0 1920x1080x24
|
||||
# user=%(ENV_USER)s
|
||||
# environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s"
|
||||
# autorestart=true
|
||||
# stopsignal=QUIT
|
||||
# stdout_logfile=/home/%(ENV_USER)s/.cache/log/xvfb.log
|
||||
# stderr_logfile=/home/%(ENV_USER)s/.cache/log/xvfb.err
|
||||
|
||||
[program:x11vnc]
|
||||
autostart=true
|
||||
priority=30
|
||||
directory=/
|
||||
#command=/usr/bin/x11vnc -display %(ENV_DISPLAY)s -xkb
|
||||
command=/usr/bin/x11vnc -display %(ENV_DISPLAY)s -rfbport 5900 -shared -forever
|
||||
user=%(ENV_USER)s
|
||||
autorestart=true
|
||||
stopsignal=QUIT
|
||||
stdout_logfile=/home/%(ENV_USER)s/.cache/log/x11vnc.log
|
||||
stderr_logfile=/home/%(ENV_USER)s/.cache/log/x11vnc.err
|
||||
|
||||
[program:de]
|
||||
autostart=true
|
||||
priority=50
|
||||
directory=/home/%(ENV_USER)s
|
||||
command=/usr/bin/startxfce4
|
||||
#command=/usr/bin/mate-session
|
||||
#command=/usr/bin/startlxqt
|
||||
#command=/usr/bin/dbus-launch startxfce4
|
||||
#command=/usr/bin/dbus-launch xfce4-session
|
||||
#command=/usr/bin/dbus-launch startplasma-x11
|
||||
user=%(ENV_USER)s
|
||||
autorestart=true
|
||||
stopsignal=QUIT
|
||||
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
|
||||
stdout_logfile=/home/%(ENV_USER)s/.cache/log/de.log
|
||||
stderr_logfile=/home/%(ENV_USER)s/.cache/log/de.err
|
||||
|
||||
## Experimental launch directly to steam big picture... (this is cool, but not ideal for headless)
|
||||
# [program:steam]
|
||||
# autostart=true
|
||||
# priority=50
|
||||
# directory=/home/%(ENV_USER)s
|
||||
# command=/usr/bin/steam -bigpicture
|
||||
# user=%(ENV_USER)s
|
||||
# autorestart=true
|
||||
# stopsignal=QUIT
|
||||
# environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
|
||||
# stdout_logfile=/home/%(ENV_USER)s/.cache/log/steam.log
|
||||
# stderr_logfile=/home/%(ENV_USER)s/.cache/log/steam.err
|
||||
|
||||
[program:novnc]
|
||||
autostart=true
|
||||
priority=100
|
||||
command=/opt/noVNC/utils/launch.sh --vnc localhost:5900 --listen 8083
|
||||
#command=/usr/share/novnc/utils/launch.sh --vnc localhost:5900 --listen 8083
|
||||
#command=/usr/local/bin/websockify -D --web=/usr/share/novnc/ --cert=/etc/ssl/novnc.pem 8083 localhost:5900
|
||||
user=%(ENV_USER)s
|
||||
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s"
|
||||
autorestart=true
|
||||
152
overlay/etc/supervisord.conf
Normal file
@@ -0,0 +1,152 @@
|
||||
; Sample supervisor config file.
|
||||
;
|
||||
; For more information on the config file, please see:
|
||||
; http://supervisord.org/configuration.html
|
||||
;
|
||||
; Notes:
|
||||
; - Shell expansion ("~" or "$HOME") is not supported. Environment
|
||||
; variables can be expanded using this syntax: "%(ENV_HOME)s".
|
||||
; - Quotes around values are not supported, except in the case of
|
||||
; the environment= options as shown below.
|
||||
; - Comments must have a leading space: "a=b ;comment" not "a=b;comment".
|
||||
; - Command will be truncated if it looks like a config file comment, e.g.
|
||||
; "command=bash -c 'foo ; bar'" will truncate to "command=bash -c 'foo ".
|
||||
|
||||
[unix_http_server]
|
||||
file=/run/supervisor.sock ; the path to the socket file
|
||||
;chmod=0700 ; socket file mode (default 0700)
|
||||
;chown=nobody:nogroup ; socket file uid:gid owner
|
||||
;username=user ; default is no username (open server)
|
||||
;password=123 ; default is no password (open server)
|
||||
|
||||
;[inet_http_server] ; inet (TCP) server disabled by default
|
||||
;port=127.0.0.1:9001 ; ip_address:port specifier, *:port for all iface
|
||||
;username=user ; default is no username (open server)
|
||||
;password=123 ; default is no password (open server)
|
||||
|
||||
[supervisord]
|
||||
logfile=/var/log/supervisord.log ; main log file; default $CWD/supervisord.log
|
||||
logfile_maxbytes=50MB ; max main logfile bytes b4 rotation; default 50MB
|
||||
logfile_backups=10 ; # of main logfile backups; 0 means none, default 10
|
||||
loglevel=info ; log level; default info; others: debug,warn,trace
|
||||
pidfile=/run/supervisord.pid ; supervisord pidfile; default supervisord.pid
|
||||
nodaemon=false ; start in foreground if true; default false
|
||||
minfds=1024 ; min. avail startup file descriptors; default 1024
|
||||
minprocs=200 ; min. avail process descriptors;default 200
|
||||
;umask=022 ; process file creation umask; default 022
|
||||
;user=supervisord ; setuid to this UNIX account at startup; recommended if root
|
||||
;identifier=supervisor ; supervisord identifier, default is 'supervisor'
|
||||
;directory=/tmp ; default is not to cd during start
|
||||
;nocleanup=true ; don't clean up tempfiles at start; default false
|
||||
childlogdir=/var/log/supervisor ; 'AUTO' child log dir, default $TEMP
|
||||
;environment=KEY="value" ; key value pairs to add to environment
|
||||
;strip_ansi=false ; strip ansi escape codes in logs; def. false
|
||||
|
||||
; The rpcinterface:supervisor section must remain in the config file for
|
||||
; RPC (supervisorctl/web interface) to work. Additional interfaces may be
|
||||
; added by defining them in separate [rpcinterface:x] sections.
|
||||
|
||||
[rpcinterface:supervisor]
|
||||
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
|
||||
|
||||
; The supervisorctl section configures how supervisorctl will connect to
|
||||
; supervisord. configure it match the settings in either the unix_http_server
|
||||
; or inet_http_server section.
|
||||
|
||||
[supervisorctl]
|
||||
serverurl=unix:///run/supervisor.sock ; use a unix:// URL for a unix socket
|
||||
;serverurl=http://127.0.0.1:9001 ; use an http:// url to specify an inet socket
|
||||
;username=chris ; should be same as in [*_http_server] if set
|
||||
;password=123 ; should be same as in [*_http_server] if set
|
||||
;prompt=mysupervisor ; cmd line prompt (default "supervisor")
|
||||
;history_file=~/.sc_history ; use readline history if available
|
||||
|
||||
; The sample program section below shows all possible program subsection values.
|
||||
; Create one or more 'real' program: sections to be able to control them under
|
||||
; supervisor.
|
||||
|
||||
;[program:theprogramname]
|
||||
;command=/bin/cat ; the program (relative uses PATH, can take args)
|
||||
;process_name=%(program_name)s ; process_name expr (default %(program_name)s)
|
||||
;numprocs=1 ; number of processes copies to start (def 1)
|
||||
;directory=/tmp ; directory to cwd to before exec (def no cwd)
|
||||
;umask=022 ; umask for process (default None)
|
||||
;priority=999 ; the relative start priority (default 999)
|
||||
;autostart=true ; start at supervisord start (default: true)
|
||||
;startsecs=1 ; # of secs prog must stay up to be running (def. 1)
|
||||
;startretries=3 ; max # of serial start failures when starting (default 3)
|
||||
;autorestart=unexpected ; when to restart if exited after running (def: unexpected)
|
||||
;exitcodes=0 ; 'expected' exit codes used with autorestart (default 0)
|
||||
;stopsignal=QUIT ; signal used to kill process (default TERM)
|
||||
;stopwaitsecs=10 ; max num secs to wait b4 SIGKILL (default 10)
|
||||
;stopasgroup=false ; send stop signal to the UNIX process group (default false)
|
||||
;killasgroup=false ; SIGKILL the UNIX process group (def false)
|
||||
;user=chrism ; setuid to this UNIX account to run the program
|
||||
;redirect_stderr=true ; redirect proc stderr to stdout (default false)
|
||||
;stdout_logfile=/a/path ; stdout log path, NONE for none; default AUTO
|
||||
;stdout_logfile_maxbytes=1MB ; max # logfile bytes b4 rotation (default 50MB)
|
||||
;stdout_logfile_backups=10 ; # of stdout logfile backups (0 means none, default 10)
|
||||
;stdout_capture_maxbytes=1MB ; number of bytes in 'capturemode' (default 0)
|
||||
;stdout_events_enabled=false ; emit events on stdout writes (default false)
|
||||
;stdout_syslog=false ; send stdout to syslog with process name (default false)
|
||||
;stderr_logfile=/a/path ; stderr log path, NONE for none; default AUTO
|
||||
;stderr_logfile_maxbytes=1MB ; max # logfile bytes b4 rotation (default 50MB)
|
||||
;stderr_logfile_backups=10 ; # of stderr logfile backups (0 means none, default 10)
|
||||
;stderr_capture_maxbytes=1MB ; number of bytes in 'capturemode' (default 0)
|
||||
;stderr_events_enabled=false ; emit events on stderr writes (default false)
|
||||
;stderr_syslog=false ; send stderr to syslog with process name (default false)
|
||||
;environment=A="1",B="2" ; process environment additions (def no adds)
|
||||
;serverurl=AUTO ; override serverurl computation (childutils)
|
||||
|
||||
; The sample eventlistener section below shows all possible eventlistener
|
||||
; subsection values. Create one or more 'real' eventlistener: sections to be
|
||||
; able to handle event notifications sent by supervisord.
|
||||
|
||||
;[eventlistener:theeventlistenername]
|
||||
;command=/bin/eventlistener ; the program (relative uses PATH, can take args)
|
||||
;process_name=%(program_name)s ; process_name expr (default %(program_name)s)
|
||||
;numprocs=1 ; number of processes copies to start (def 1)
|
||||
;events=EVENT ; event notif. types to subscribe to (req'd)
|
||||
;buffer_size=10 ; event buffer queue size (default 10)
|
||||
;directory=/tmp ; directory to cwd to before exec (def no cwd)
|
||||
;umask=022 ; umask for process (default None)
|
||||
;priority=-1 ; the relative start priority (default -1)
|
||||
;autostart=true ; start at supervisord start (default: true)
|
||||
;startsecs=1 ; # of secs prog must stay up to be running (def. 1)
|
||||
;startretries=3 ; max # of serial start failures when starting (default 3)
|
||||
;autorestart=unexpected ; autorestart if exited after running (def: unexpected)
|
||||
;exitcodes=0 ; 'expected' exit codes used with autorestart (default 0)
|
||||
;stopsignal=QUIT ; signal used to kill process (default TERM)
|
||||
;stopwaitsecs=10 ; max num secs to wait b4 SIGKILL (default 10)
|
||||
;stopasgroup=false ; send stop signal to the UNIX process group (default false)
|
||||
;killasgroup=false ; SIGKILL the UNIX process group (def false)
|
||||
;user=chrism ; setuid to this UNIX account to run the program
|
||||
;redirect_stderr=false ; redirect_stderr=true is not allowed for eventlisteners
|
||||
;stdout_logfile=/a/path ; stdout log path, NONE for none; default AUTO
|
||||
;stdout_logfile_maxbytes=1MB ; max # logfile bytes b4 rotation (default 50MB)
|
||||
;stdout_logfile_backups=10 ; # of stdout logfile backups (0 means none, default 10)
|
||||
;stdout_events_enabled=false ; emit events on stdout writes (default false)
|
||||
;stdout_syslog=false ; send stdout to syslog with process name (default false)
|
||||
;stderr_logfile=/a/path ; stderr log path, NONE for none; default AUTO
|
||||
;stderr_logfile_maxbytes=1MB ; max # logfile bytes b4 rotation (default 50MB)
|
||||
;stderr_logfile_backups=10 ; # of stderr logfile backups (0 means none, default 10)
|
||||
;stderr_events_enabled=false ; emit events on stderr writes (default false)
|
||||
;stderr_syslog=false ; send stderr to syslog with process name (default false)
|
||||
;environment=A="1",B="2" ; process environment additions
|
||||
;serverurl=AUTO ; override serverurl computation (childutils)
|
||||
|
||||
; The sample group section below shows all possible group values. Create one
|
||||
; or more 'real' group: sections to create "heterogeneous" process groups.
|
||||
|
||||
;[group:thegroupname]
|
||||
;programs=progname1,progname2 ; each refers to 'x' in [program:x] definitions
|
||||
;priority=999 ; the relative start priority (default 999)
|
||||
|
||||
; The [include] section can just contain the "files" setting. This
|
||||
; setting can list multiple files (separated by whitespace or
|
||||
; newlines). It can also contain wildcards. The filenames are
|
||||
; interpreted as relative to this file. Included files *cannot*
|
||||
; include files themselves.
|
||||
|
||||
[include]
|
||||
files = /etc/supervisor.d/*.ini
|
||||
@@ -102,14 +102,14 @@ index cb6a9fd..4d599e1 100644
|
||||
UI.rfb.focus();
|
||||
+
|
||||
+ let audio_url;
|
||||
+ let host = window.location.hostname;
|
||||
+ let port = 32123;
|
||||
+ // let host = window.location.hostname;
|
||||
+ // let port = '<PORT_AUDIO_WEBSOCKET>';
|
||||
+ if (window.location.protocol === "https:") {
|
||||
+ audio_url = 'wss';
|
||||
+ } else {
|
||||
+ audio_url = 'ws';
|
||||
+ }
|
||||
+ audio_url += '://' + host + ':' + port;
|
||||
+ audio_url += '://' + window.location.host + '/audiowebsock';
|
||||
+
|
||||
+ UI.webaudio = new WebAudio(audio_url);
|
||||
+ UI.toggleAudio();
|
||||
@@ -326,14 +326,14 @@ index 8e2f5cb..d3cf6ab 100644
|
||||
// successfully connected to a server
|
||||
function connectedToServer(e) {
|
||||
+ let audio_url;
|
||||
+ let host = window.location.hostname;
|
||||
+ let port = 32123;
|
||||
+ // let host = window.location.hostname;
|
||||
+ // let port = '<PORT_AUDIO_WEBSOCKET>';
|
||||
+ if (window.location.protocol === "https:") {
|
||||
+ audio_url = 'wss';
|
||||
+ } else {
|
||||
+ audio_url = 'ws';
|
||||
+ }
|
||||
+ audio_url += '://' + host + ':' + port;
|
||||
+ audio_url += '://' + window.location.host + '/audiowebsock';
|
||||
+
|
||||
+ wa = new WebAudio(audio_url);
|
||||
+ document.getElementById('toggleAudioButton').style.display = "block";
|
||||
@@ -360,7 +360,7 @@ index 8e2f5cb..d3cf6ab 100644
|
||||
+ if (wa.connected) {
|
||||
+ console.log('Stopping audio...')
|
||||
+ wa.stop();
|
||||
+ document.getElementById('toggleAudioButton').innerText = "Enable Audio (requires access to port 32123)";
|
||||
+ document.getElementById('toggleAudioButton').innerText = "Enable Audio";
|
||||
+ } else {
|
||||
+ console.log('Starting audio websocket on: ' + audio_url)
|
||||
+ wa.start();
|
||||
@@ -410,7 +410,7 @@ index 8e2f5cb..d3cf6ab 100644
|
||||
|
||||
<body>
|
||||
<div id="top_bar">
|
||||
+ <div id="toggleAudioButton">Enable Audio (requires access to port 32123)</div>
|
||||
+ <div id="toggleAudioButton">Enable Audio</div>
|
||||
<div id="status">Loading</div>
|
||||
<div id="sendCtrlAltDelButton">Send CtrlAltDel</div>
|
||||
</div>
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
|
||||
PUID=${PUID:-99}
|
||||
PGID=${PGID:-100}
|
||||
UMASK=${UMASK:-000}
|
||||
USER_PASSWORD=${USER_PASSWORD:-password}
|
||||
|
||||
echo "**** Configure default user ****"
|
||||
|
||||
echo "Setting run user uid=${PGID}(${USER}) gid=${PUID}(${USER})"
|
||||
groupmod -o -g "${PGID}" ${USER}
|
||||
usermod -o -u "${PUID}" ${USER}
|
||||
|
||||
|
||||
echo "Setting umask to ${UMASK}";
|
||||
umask ${UMASK}
|
||||
|
||||
|
||||
# Setup home directory and permissions
|
||||
echo "Adding default home directory template"
|
||||
mkdir -p ${USER_HOME}
|
||||
chown -R ${PUID}:${PGID} /etc/home_directory_template
|
||||
rsync -aq /etc/home_directory_template/ ${USER_HOME}/
|
||||
|
||||
|
||||
# Set the root and user password
|
||||
echo "Setting root password"
|
||||
echo "root:${USER_PASSWORD}" | chpasswd
|
||||
echo "Setting user password"
|
||||
echo "${USER}:${USER_PASSWORD}" | chpasswd
|
||||
|
||||
echo "DONE"
|
||||
@@ -1,10 +0,0 @@
|
||||
|
||||
# Generate new SSH host keys if they dont exist
|
||||
if [[ ! -f /etc/ssh/ssh_host_rsa_key ]]; then
|
||||
echo "**** Generating SSH keys ****";
|
||||
/usr/bin/ssh-keygen -A
|
||||
fi
|
||||
mkdir -p /run/sshd
|
||||
chmod 744 /run/sshd
|
||||
|
||||
echo "DONE"
|
||||
@@ -1,32 +0,0 @@
|
||||
# Configure system paths
|
||||
echo "**** Configure system paths ****";
|
||||
sed -i "/ <user>/c\ <user>${USER}</user>" /usr/share/dbus-1/system.conf
|
||||
if [ ! -d /tmp/xdg ]; then
|
||||
mkdir -p /tmp/xdg
|
||||
fi
|
||||
|
||||
echo "Configure dbus";
|
||||
# Remove old dbus session
|
||||
rm -rf ${USER_HOME}/.dbus/session-bus/* 2> /dev/null
|
||||
# Remove old dbus pids
|
||||
mkdir -p /var/run/dbus
|
||||
chown -R ${PUID}:${PGID} /var/run/dbus/
|
||||
chmod -R 770 /var/run/dbus/
|
||||
# Generate a dbus machine ID
|
||||
dbus-uuidgen > /var/lib/dbus/machine-id
|
||||
|
||||
echo "Configure X Windows context"
|
||||
chown -R ${PUID}:${PGID} /tmp/xdg
|
||||
chmod -R 0700 /tmp/xdg
|
||||
|
||||
echo "Configure X Windows session"
|
||||
rm -rfv /tmp/.ICE-unix*
|
||||
mkdir -p /tmp/.ICE-unix
|
||||
chown root:root /tmp/.ICE-unix/
|
||||
chmod 1777 /tmp/.ICE-unix/
|
||||
|
||||
echo "Remove old lockfiles"
|
||||
find /var/run/dbus -name "pid" -exec rm -f {} \;
|
||||
find /tmp -name ".X99*" -exec rm -f {} \;
|
||||
|
||||
echo "DONE"
|
||||
@@ -1,20 +0,0 @@
|
||||
|
||||
echo "**** Configure pulseaudio socket ****"
|
||||
sed -i 's|^; default-server.*$|default-server = unix:/tmp/pulseaudio.socket|' /etc/pulse/client.conf
|
||||
sed -i 's|^load-module module-native-protocol-unix.*$|load-module module-native-protocol-unix socket=/tmp/pulseaudio.socket auth-anonymous=1|' \
|
||||
/etc/pulse/default.pa
|
||||
chown -R ${USER} /etc/pulse
|
||||
|
||||
# Credits for this audio patch:
|
||||
# - https://github.com/novnc/noVNC/issues/302
|
||||
# - https://github.com/vexingcodes/dwarf-fortress-docker
|
||||
# - https://github.com/calebj/noVNC
|
||||
if [ -f /opt/noVNC/audio.patch ]; then
|
||||
echo "**** Patching noVNC with audio websocket ****"
|
||||
pushd /opt/noVNC/ &> /dev/null
|
||||
patch -p1 --input=/opt/noVNC/audio.patch --batch --quiet
|
||||
popd &> /dev/null
|
||||
rm /opt/noVNC/audio.patch
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
@@ -1,64 +0,0 @@
|
||||
|
||||
# Fech NVIDIA GPU device (if one exists)
|
||||
if [ "$NVIDIA_VISIBLE_DEVICES" == "all" ]; then
|
||||
export gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2> /dev/null | sed -n 2p)
|
||||
elif [ -z "$NVIDIA_VISIBLE_DEVICES" ]; then
|
||||
export gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2> /dev/null | sed -n 2p)
|
||||
else
|
||||
export gpu_select=$(nvidia-smi --format=csv --id=$(echo "$NVIDIA_VISIBLE_DEVICES" | cut -d ',' -f1) --query-gpu=uuid | sed -n 2p)
|
||||
if [ -z "$gpu_select" ]; then
|
||||
export gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2> /dev/null | sed -n 2p)
|
||||
fi
|
||||
fi
|
||||
|
||||
export nvidia_pci_address="$(nvidia-smi --format=csv --query-gpu=pci.bus_id --id="${gpu_select}" 2> /dev/null | sed -n 2p | cut -d ':' -f2,3)"
|
||||
export nvidia_gpu_name=$(nvidia-smi --format=csv --query-gpu=name --id="${gpu_select}" | sed -n 2p 2> /dev/null)
|
||||
export nvidia_host_driver_version="$(nvidia-smi 2> /dev/null | grep NVIDIA-SMI | cut -d ' ' -f3)"
|
||||
|
||||
function download_driver {
|
||||
mkdir -p ${USER_HOME}/.cache/nvidia
|
||||
|
||||
if [[ ! -f "${USER_HOME}/.cache/nvidia/NVIDIA_${nvidia_host_driver_version}.run" ]]; then
|
||||
echo "Downloading driver"
|
||||
wget -q --show-progress --progress=bar:force:noscroll \
|
||||
-O /tmp/NVIDIA.run \
|
||||
http://download.nvidia.com/XFree86/Linux-x86_64/${nvidia_host_driver_version}/NVIDIA-Linux-x86_64-${nvidia_host_driver_version}.run
|
||||
[[ $? -gt 0 ]] && echo "Error downloading driver. Exit!" && return 1
|
||||
|
||||
mv /tmp/NVIDIA.run ${USER_HOME}/.cache/nvidia/NVIDIA_${nvidia_host_driver_version}.run
|
||||
fi
|
||||
}
|
||||
|
||||
function install_driver {
|
||||
# Check here if the currently installed version matches using nvidia-settings
|
||||
nvidia_settings_version=$(nvidia-settings --version 2> /dev/null | grep version | cut -d ' ' -f 4)
|
||||
[[ "${nvidia_settings_version}x" == "${nvidia_host_driver_version}x" ]] && return 0
|
||||
|
||||
# Download the driver (if it does not yet exist locally)
|
||||
download_driver
|
||||
|
||||
echo "Installing driver"
|
||||
chmod +x ${USER_HOME}/.cache/nvidia/NVIDIA_${nvidia_host_driver_version}.run
|
||||
${USER_HOME}/.cache/nvidia/NVIDIA_${nvidia_host_driver_version}.run \
|
||||
--silent \
|
||||
--accept-license \
|
||||
--no-kernel-module \
|
||||
--install-compat32-libs \
|
||||
--no-nouveau-check \
|
||||
--no-nvidia-modprobe \
|
||||
--no-rpms \
|
||||
--no-backup \
|
||||
--no-check-for-alternate-installs \
|
||||
--no-libglx-indirect \
|
||||
--no-install-libglvnd \
|
||||
> ${USER_HOME}/.cache/nvidia/last_install.log 2>&1
|
||||
}
|
||||
|
||||
if [[ -z ${nvidia_pci_address} ]]; then
|
||||
echo "**** No NVIDIA device found ****";
|
||||
else
|
||||
echo "**** Found NVIDIA device '${nvidia_gpu_name}' ****";
|
||||
install_driver
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
@@ -1,57 +0,0 @@
|
||||
|
||||
# Fech NVIDIA GPU device (if one exists)
|
||||
if [ "$NVIDIA_VISIBLE_DEVICES" == "all" ]; then
|
||||
export gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2> /dev/null | sed -n 2p)
|
||||
elif [ -z "$NVIDIA_VISIBLE_DEVICES" ]; then
|
||||
export gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2> /dev/null | sed -n 2p)
|
||||
else
|
||||
export gpu_select=$(nvidia-smi --format=csv --id=$(echo "$NVIDIA_VISIBLE_DEVICES" | cut -d ',' -f1) --query-gpu=uuid | sed -n 2p)
|
||||
if [ -z "$gpu_select" ]; then
|
||||
export gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2> /dev/null | sed -n 2p)
|
||||
fi
|
||||
fi
|
||||
|
||||
export nvidia_gpu_hex_id=$(nvidia-smi --format=csv --query-gpu=pci.bus_id --id="${gpu_select}" 2> /dev/null | sed -n 2p)
|
||||
|
||||
# Fech current configuration (if modified in UI)
|
||||
if [ -f "${USER_HOME}/.config/xfce4/xfconf/xfce-perchannel-xml/displays.xml" ]; then
|
||||
new_display_sizew=$(cat ${USER_HOME}/.config/xfce4/xfconf/xfce-perchannel-xml/displays.xml | grep Resolution | head -n1 | grep -oP '(?<=value=").*?(?=")' | cut -d'x' -f1)
|
||||
new_display_sizeh=$(cat ${USER_HOME}/.config/xfce4/xfconf/xfce-perchannel-xml/displays.xml | grep Resolution | head -n1 | grep -oP '(?<=value=").*?(?=")' | cut -d'x' -f2)
|
||||
if [ "${new_display_sizew}x" != "x" ] && [ "${new_display_sizeh}x" != "x" ]; then
|
||||
export DISPLAY_SIZEW="${new_display_sizew}"
|
||||
export DISPLAY_SIZEH="${new_display_sizeh}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Configure a NVIDIA X11 config
|
||||
function configure_nvidia_x_server {
|
||||
# Configure x to be run by anyone
|
||||
if grep -Fxq "allowed_users=console" /etc/X11/Xwrapper.config; then
|
||||
echo "Configure Xwrapper.config"
|
||||
sed -i "s/allowed_users=console/allowed_users=anybody/" /etc/X11/Xwrapper.config
|
||||
fi
|
||||
|
||||
# Configure xorg for NVIDIA
|
||||
echo "Configuring X11 with GPU ID: '${gpu_select}'"
|
||||
nvidia_gpu_hex_id=$(nvidia-smi --format=csv --query-gpu=pci.bus_id --id="${gpu_select}" 2> /dev/null | sed -n 2p)
|
||||
IFS=":." ARR_ID=(${nvidia_gpu_hex_id})
|
||||
unset IFS
|
||||
bus_id=PCI:$((16#${ARR_ID[1]})):$((16#${ARR_ID[2]})):$((16#${ARR_ID[3]}))
|
||||
echo "Configuring X11 with PCI bus ID: '${bus_id}'"
|
||||
export MODELINE=$(cvt -r "${DISPLAY_SIZEW}" "${DISPLAY_SIZEH}" "${DISPLAY_REFRESH}" | sed -n 2p)
|
||||
echo "Writing X11 config with ${MODELINE}"
|
||||
nvidia-xconfig --virtual="${DISPLAY_SIZEW}x${DISPLAY_SIZEH}" --depth="${DISPLAY_CDEPTH}" --mode=$(echo "${MODELINE}" | awk '{print $2}' | tr -d '"') --allow-empty-initial-configuration --no-probe-all-gpus --busid="${bus_id}" --only-one-x-screen --connected-monitor="${DISPLAY_VIDEO_PORT}"
|
||||
sed -i '/Driver\s\+"nvidia"/a\ Option "ModeValidation" "NoMaxPClkCheck, NoEdidMaxPClkCheck, NoMaxSizeCheck, NoHorizSyncCheck, NoVertRefreshCheck, NoVirtualSizeCheck, NoExtendedGpuCapabilitiesCheck, NoTotalSizeCheck, NoDualLinkDVICheck, NoDisplayPortBandwidthCheck, AllowNon3DVisionModes, AllowNonHDMI3DModes, AllowNonEdidModes, NoEdidHDMI2Check, AllowDpInterlaced"' /etc/X11/xorg.conf
|
||||
sed -i '/Section\s\+"Monitor"/a\ '"${MODELINE}" /etc/X11/xorg.conf
|
||||
}
|
||||
|
||||
|
||||
if [[ -z ${nvidia_gpu_hex_id} ]]; then
|
||||
echo "**** Generate default xorg.conf ****";
|
||||
# TODO: Configure xorg.conf with no NVIDIA GPU
|
||||
else
|
||||
echo "**** Generate NVIDIA xorg.conf ****";
|
||||
configure_nvidia_x_server
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
@@ -7,3 +7,8 @@
|
||||
|
||||
alias ls='ls --color=auto'
|
||||
PS1='[\u@\h \W]\$ '
|
||||
|
||||
# Export user's home directory bin directories
|
||||
PATH=$PATH:$HOME/.local/bin:$HOME/bin
|
||||
# Export /usr/games
|
||||
PATH=$PATH:/usr/games
|
||||
@@ -0,0 +1,7 @@
|
||||
[Default Applications]
|
||||
x-scheme-handler/http=xfce4-web-browser.desktop
|
||||
x-scheme-handler/https=xfce4-web-browser.desktop
|
||||
|
||||
[Added Associations]
|
||||
x-scheme-handler/http=xfce4-web-browser.desktop;
|
||||
x-scheme-handler/https=xfce4-web-browser.desktop;
|
||||
@@ -0,0 +1 @@
|
||||
WebBrowser=custom-WebBrowser
|
||||
@@ -27,24 +27,45 @@
|
||||
<property name="workspace0" type="empty">
|
||||
<property name="color-style" type="int" value="1"/>
|
||||
<property name="image-style" type="int" value="5"/>
|
||||
<property name="last-image" type="string" value="/usr/share/images/desktop-base/default"/>
|
||||
<property name="last-image" type="string" value="/usr/share/backgrounds/steam.jpg"/>
|
||||
</property>
|
||||
<property name="workspace1" type="empty">
|
||||
<property name="color-style" type="int" value="1"/>
|
||||
<property name="image-style" type="int" value="5"/>
|
||||
<property name="last-image" type="string" value="/usr/share/images/desktop-base/default"/>
|
||||
<property name="last-image" type="string" value="/usr/share/backgrounds/steam.jpg"/>
|
||||
</property>
|
||||
<property name="workspace2" type="empty">
|
||||
<property name="color-style" type="int" value="1"/>
|
||||
<property name="image-style" type="int" value="5"/>
|
||||
<property name="last-image" type="string" value="/usr/share/images/desktop-base/default"/>
|
||||
<property name="last-image" type="string" value="/usr/share/backgrounds/steam.jpg"/>
|
||||
</property>
|
||||
<property name="workspace3" type="empty">
|
||||
<property name="color-style" type="int" value="1"/>
|
||||
<property name="image-style" type="int" value="5"/>
|
||||
<property name="last-image" type="string" value="/usr/share/images/desktop-base/default"/>
|
||||
<property name="last-image" type="string" value="/usr/share/backgrounds/steam.jpg"/>
|
||||
</property>
|
||||
</property>
|
||||
</property>
|
||||
</property>
|
||||
<property name="desktop-icons" type="empty">
|
||||
<property name="style" type="int" value="0"/>
|
||||
<property name="icon-size" type="uint" value="48"/>
|
||||
<property name="show-tooltips" type="bool" value="true"/>
|
||||
<property name="show-thumbnails" type="bool" value="true"/>
|
||||
</property>
|
||||
<property name="last" type="empty">
|
||||
<property name="window-width" type="int" value="653"/>
|
||||
<property name="window-height" type="int" value="558"/>
|
||||
</property>
|
||||
<property name="windowlist-menu" type="empty">
|
||||
<property name="show-icons" type="bool" value="true"/>
|
||||
<property name="show-add-remove-workspaces" type="bool" value="false"/>
|
||||
<property name="show-workspace-names" type="bool" value="false"/>
|
||||
<property name="show" type="bool" value="true"/>
|
||||
</property>
|
||||
<property name="desktop-menu" type="empty">
|
||||
<property name="show-delete" type="bool" value="false"/>
|
||||
<property name="show-icons" type="bool" value="true"/>
|
||||
<property name="show" type="bool" value="true"/>
|
||||
</property>
|
||||
</channel>
|
||||
@@ -7,15 +7,14 @@
|
||||
<property name="dark-mode" type="bool" value="true"/>
|
||||
<property name="panel-1" type="empty">
|
||||
<property name="position" type="string" value="p=6;x=0;y=0"/>
|
||||
<property name="length" type="uint" value="100"/>
|
||||
<property name="length" type="double" value="100"/>
|
||||
<property name="position-locked" type="bool" value="true"/>
|
||||
<property name="icon-size" type="uint" value="16"/>
|
||||
<property name="size" type="uint" value="26"/>
|
||||
<property name="icon-size" type="uint" value="36"/>
|
||||
<property name="size" type="uint" value="40"/>
|
||||
<property name="plugin-ids" type="array">
|
||||
<value type="int" value="1"/>
|
||||
<value type="int" value="2"/>
|
||||
<value type="int" value="3"/>
|
||||
<value type="int" value="4"/>
|
||||
<value type="int" value="5"/>
|
||||
<value type="int" value="6"/>
|
||||
<value type="int" value="8"/>
|
||||
@@ -23,13 +22,17 @@
|
||||
<value type="int" value="11"/>
|
||||
<value type="int" value="12"/>
|
||||
<value type="int" value="13"/>
|
||||
<value type="int" value="14"/>
|
||||
</property>
|
||||
<property name="background-style" type="uint" value="0"/>
|
||||
<property name="mode" type="uint" value="0"/>
|
||||
<property name="autohide-behavior" type="uint" value="0"/>
|
||||
<property name="nrows" type="uint" value="1"/>
|
||||
</property>
|
||||
</property>
|
||||
<property name="plugins" type="empty">
|
||||
<property name="plugin-1" type="string" value="applicationsmenu"/>
|
||||
<property name="plugin-1" type="string" value="applicationsmenu">
|
||||
<property name="button-icon" type="string" value="steam-headless"/>
|
||||
</property>
|
||||
<property name="plugin-2" type="string" value="tasklist">
|
||||
<property name="grouping" type="uint" value="1"/>
|
||||
</property>
|
||||
@@ -37,7 +40,6 @@
|
||||
<property name="expand" type="bool" value="true"/>
|
||||
<property name="style" type="uint" value="0"/>
|
||||
</property>
|
||||
<property name="plugin-4" type="string" value="pager"/>
|
||||
<property name="plugin-5" type="string" value="separator">
|
||||
<property name="style" type="uint" value="0"/>
|
||||
</property>
|
||||
@@ -53,10 +55,11 @@
|
||||
<property name="plugin-11" type="string" value="separator">
|
||||
<property name="style" type="uint" value="0"/>
|
||||
</property>
|
||||
<property name="plugin-12" type="string" value="clock"/>
|
||||
<property name="plugin-12" type="string" value="clock">
|
||||
<property name="mode" type="uint" value="2"/>
|
||||
</property>
|
||||
<property name="plugin-13" type="string" value="separator">
|
||||
<property name="style" type="uint" value="0"/>
|
||||
</property>
|
||||
<property name="plugin-14" type="string" value="actions"/>
|
||||
</property>
|
||||
</channel>
|
||||
</channel>
|
||||
@@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<channel name="xfwm4" version="1.0">
|
||||
<property name="general" type="empty">
|
||||
<property name="activate_action" type="string" value="bring"/>
|
||||
<property name="borderless_maximize" type="bool" value="true"/>
|
||||
<property name="box_move" type="bool" value="false"/>
|
||||
<property name="box_resize" type="bool" value="false"/>
|
||||
<property name="button_layout" type="string" value="O|SHMC"/>
|
||||
<property name="button_offset" type="int" value="0"/>
|
||||
<property name="button_spacing" type="int" value="0"/>
|
||||
<property name="click_to_focus" type="bool" value="true"/>
|
||||
<property name="cycle_apps_only" type="bool" value="false"/>
|
||||
<property name="cycle_draw_frame" type="bool" value="true"/>
|
||||
<property name="cycle_raise" type="bool" value="false"/>
|
||||
<property name="cycle_hidden" type="bool" value="true"/>
|
||||
<property name="cycle_minimum" type="bool" value="true"/>
|
||||
<property name="cycle_minimized" type="bool" value="false"/>
|
||||
<property name="cycle_preview" type="bool" value="true"/>
|
||||
<property name="cycle_tabwin_mode" type="int" value="0"/>
|
||||
<property name="cycle_workspaces" type="bool" value="false"/>
|
||||
<property name="double_click_action" type="string" value="maximize"/>
|
||||
<property name="double_click_distance" type="int" value="5"/>
|
||||
<property name="double_click_time" type="int" value="250"/>
|
||||
<property name="easy_click" type="string" value="Alt"/>
|
||||
<property name="focus_delay" type="int" value="250"/>
|
||||
<property name="focus_hint" type="bool" value="true"/>
|
||||
<property name="focus_new" type="bool" value="true"/>
|
||||
<property name="frame_opacity" type="int" value="100"/>
|
||||
<property name="frame_border_top" type="int" value="0"/>
|
||||
<property name="full_width_title" type="bool" value="true"/>
|
||||
<property name="horiz_scroll_opacity" type="bool" value="false"/>
|
||||
<property name="inactive_opacity" type="int" value="100"/>
|
||||
<property name="maximized_offset" type="int" value="0"/>
|
||||
<property name="mousewheel_rollup" type="bool" value="true"/>
|
||||
<property name="move_opacity" type="int" value="100"/>
|
||||
<property name="placement_mode" type="string" value="center"/>
|
||||
<property name="placement_ratio" type="int" value="20"/>
|
||||
<property name="popup_opacity" type="int" value="100"/>
|
||||
<property name="prevent_focus_stealing" type="bool" value="false"/>
|
||||
<property name="raise_delay" type="int" value="250"/>
|
||||
<property name="raise_on_click" type="bool" value="true"/>
|
||||
<property name="raise_on_focus" type="bool" value="false"/>
|
||||
<property name="raise_with_any_button" type="bool" value="true"/>
|
||||
<property name="repeat_urgent_blink" type="bool" value="false"/>
|
||||
<property name="resize_opacity" type="int" value="100"/>
|
||||
<property name="scroll_workspaces" type="bool" value="false"/>
|
||||
<property name="shadow_delta_height" type="int" value="0"/>
|
||||
<property name="shadow_delta_width" type="int" value="0"/>
|
||||
<property name="shadow_delta_x" type="int" value="0"/>
|
||||
<property name="shadow_delta_y" type="int" value="-3"/>
|
||||
<property name="shadow_opacity" type="int" value="50"/>
|
||||
<property name="show_app_icon" type="bool" value="false"/>
|
||||
<property name="show_dock_shadow" type="bool" value="true"/>
|
||||
<property name="show_frame_shadow" type="bool" value="true"/>
|
||||
<property name="show_popup_shadow" type="bool" value="false"/>
|
||||
<property name="snap_resist" type="bool" value="false"/>
|
||||
<property name="snap_to_border" type="bool" value="true"/>
|
||||
<property name="snap_to_windows" type="bool" value="false"/>
|
||||
<property name="snap_width" type="int" value="10"/>
|
||||
<property name="vblank_mode" type="string" value="auto"/>
|
||||
<property name="theme" type="string" value="Default-xhdpi"/>
|
||||
<property name="tile_on_move" type="bool" value="true"/>
|
||||
<property name="title_alignment" type="string" value="center"/>
|
||||
<property name="title_font" type="string" value="Sans Bold 9"/>
|
||||
<property name="title_horizontal_offset" type="int" value="0"/>
|
||||
<property name="titleless_maximize" type="bool" value="false"/>
|
||||
<property name="title_shadow_active" type="string" value="false"/>
|
||||
<property name="title_shadow_inactive" type="string" value="false"/>
|
||||
<property name="title_vertical_offset_active" type="int" value="0"/>
|
||||
<property name="title_vertical_offset_inactive" type="int" value="0"/>
|
||||
<property name="toggle_workspaces" type="bool" value="false"/>
|
||||
<property name="unredirect_overlays" type="bool" value="true"/>
|
||||
<property name="urgent_blink" type="bool" value="false"/>
|
||||
<property name="use_compositing" type="bool" value="true"/>
|
||||
<property name="workspace_count" type="int" value="1"/>
|
||||
<property name="wrap_cycle" type="bool" value="false"/>
|
||||
<property name="wrap_layout" type="bool" value="false"/>
|
||||
<property name="wrap_resistance" type="int" value="10"/>
|
||||
<property name="wrap_windows" type="bool" value="false"/>
|
||||
<property name="wrap_workspaces" type="bool" value="false"/>
|
||||
<property name="zoom_desktop" type="bool" value="true"/>
|
||||
<property name="zoom_pointer" type="bool" value="true"/>
|
||||
<property name="workspace_names" type="array">
|
||||
<value type="string" value="Workspace 1"/>
|
||||
<value type="string" value="Workspace 2"/>
|
||||
<value type="string" value="Workspace 3"/>
|
||||
<value type="string" value="Workspace 4"/>
|
||||
</property>
|
||||
<property name="margin_top" type="int" value="0"/>
|
||||
</property>
|
||||
</channel>
|
||||
@@ -14,7 +14,7 @@
|
||||
<property name="EnableInputFeedbackSounds" type="empty"/>
|
||||
</property>
|
||||
<property name="Xft" type="empty">
|
||||
<property name="DPI" type="empty"/>
|
||||
<property name="DPI" type="int" value="110"/>
|
||||
<property name="Antialias" type="empty"/>
|
||||
<property name="Hinting" type="empty"/>
|
||||
<property name="HintStyle" type="empty"/>
|
||||
@@ -32,7 +32,7 @@
|
||||
<property name="MenuImages" type="empty"/>
|
||||
<property name="ButtonImages" type="empty"/>
|
||||
<property name="MenuBarAccel" type="empty"/>
|
||||
<property name="CursorThemeName" type="empty"/>
|
||||
<property name="CursorThemeName" type="string" value="default"/>
|
||||
<property name="CursorThemeSize" type="empty"/>
|
||||
<property name="DecorationLayout" type="empty"/>
|
||||
<property name="DialogsUseHeader" type="empty"/>
|
||||
@@ -41,4 +41,8 @@
|
||||
<property name="Gdk" type="empty">
|
||||
<property name="WindowScalingFactor" type="empty"/>
|
||||
</property>
|
||||
</channel>
|
||||
<property name="Xfce" type="empty">
|
||||
<property name="LastCustomDPI" type="int" value="110"/>
|
||||
<property name="SyncThemes" type="bool" value="true"/>
|
||||
</property>
|
||||
</channel>
|
||||
@@ -0,0 +1,11 @@
|
||||
"libraryfolders"
|
||||
[Desktop Entry]
|
||||
NoDisplay=true
|
||||
Version=1.0
|
||||
Encoding=UTF-8
|
||||
Type=X-XFCE-Helper
|
||||
X-XFCE-Category=WebBrowser
|
||||
X-XFCE-CommandsWithParameter=/home/default/.local/share/flatpak/exports/bin/org.mozilla.firefox "%s"
|
||||
Icon=org.mozilla.firefox
|
||||
Name=org.mozilla.firefox
|
||||
X-XFCE-Commands=/home/default/.local/share/flatpak/exports/bin/org.mozilla.firefox
|
||||
34
overlay/templates/sunshine/apps.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"env": {
|
||||
"PATH": "$(PATH):$(HOME)\/.local\/bin"
|
||||
},
|
||||
"apps": [
|
||||
{
|
||||
"name": "Desktop",
|
||||
"image-path": "desktop.png",
|
||||
"exclude-global-prep-cmd": "true"
|
||||
},
|
||||
{
|
||||
"name": "Steam Big Picture",
|
||||
"image-path": "steam.png",
|
||||
"exclude-global-prep-cmd": "true",
|
||||
"detached": [
|
||||
"\/usr\/bin\/sunshine-run \/usr\/games\/steam steam:\/\/open\/bigpicture"
|
||||
],
|
||||
"prep-cmd": [
|
||||
{
|
||||
"do": "",
|
||||
"undo": "sh -c \"sleep 7 && pkill -f -2 \/usr\/bin\/sunshine\""
|
||||
},
|
||||
{
|
||||
"do": "",
|
||||
"undo": "\/usr\/bin\/sunshine-stop"
|
||||
},
|
||||
{
|
||||
"do": "",
|
||||
"undo": "\/usr\/bin\/xfce4-close-all-windows"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
290
overlay/templates/sunshine/sunshine.conf
Normal file
@@ -0,0 +1,290 @@
|
||||
# If no external IP address is given, Sunshine will attempt to automatically detect external ip-address
|
||||
# external_ip = 123.456.789.12
|
||||
|
||||
# Set the familly of ports used by Sunshine
|
||||
# port = 47989
|
||||
|
||||
# The private key must be 2048 bits
|
||||
# pkey = /dir/pkey.pem
|
||||
|
||||
# The certificate must be signed with a 2048 bit key
|
||||
# cert = /dir/cert.pem
|
||||
|
||||
# The name displayed by Moonlight
|
||||
# If not specified, the PC's hostname is used
|
||||
# sunshine_name = Sunshine
|
||||
|
||||
# The minimum log level printed to standard out
|
||||
#
|
||||
# none -> no logs are printed to standard out
|
||||
#
|
||||
# verbose = [0]
|
||||
# debug = [1]
|
||||
# info = [2]
|
||||
# warning = [3]
|
||||
# error = [4]
|
||||
# fatal = [5]
|
||||
# none = [6]
|
||||
#
|
||||
min_log_level = info
|
||||
|
||||
# A list of commands to be run before/after all applications.
|
||||
# If any of the prep-commands fail, starting the application is aborted.
|
||||
global_prep_cmd = [{"do":"/usr/bin/xfce4-minimise-all-windows","undo":"/usr/bin/sunshine-stop"}]
|
||||
|
||||
# The origin of the remote endpoint address that is not denied for HTTP method /pin
|
||||
# Could be any of the following values:
|
||||
# pc|lan|wan
|
||||
# pc: Only localhost may access /pin
|
||||
# lan: Only those in LAN may access /pin
|
||||
# wan: Anyone may access /pin
|
||||
#
|
||||
# origin_pin_allowed = pc
|
||||
|
||||
# The origin of the remote endpoint address that is not denied for HTTPS Web UI
|
||||
# Could be any of the following values:
|
||||
# pc|lan|wan
|
||||
# pc: Only localhost may access the Web Manager
|
||||
# lan: Only those in LAN may access the Web Manager
|
||||
# wan: Anyone may access the Web Manager
|
||||
#
|
||||
# origin_web_ui_allowed = lan
|
||||
|
||||
# If UPnP is enabled, Sunshine will attempt to open ports for streaming over the internet
|
||||
# To enable it, uncomment the following line:
|
||||
# upnp = on
|
||||
|
||||
# The file where current state of Sunshine is stored
|
||||
# file_state = sunshine_state.json
|
||||
|
||||
# The file where user credentials for the UI are stored
|
||||
# By default, credentials are stored in `file_state`
|
||||
# credentials_file = sunshine_state.json
|
||||
|
||||
# The display modes advertised by Sunshine
|
||||
#
|
||||
# Some versions of Moonlight, such as Moonlight-nx (Switch),
|
||||
# rely on this list to ensure that the requested resolutions and fps
|
||||
# are supported.
|
||||
#
|
||||
# fps = [10, 30, 60, 90, 120]
|
||||
# resolutions = [
|
||||
# 352x240,
|
||||
# 480x360,
|
||||
# 858x480,
|
||||
# 1280x720,
|
||||
# 1920x1080,
|
||||
# 2560x1080,
|
||||
# 3440x1440,
|
||||
# 1920x1200,
|
||||
# 3860x2160,
|
||||
# 3840x1600,
|
||||
# ]
|
||||
|
||||
# Sometimes it may be usefull to map keybindings.
|
||||
# Wayland won't allow clients to capture the Win Key for example
|
||||
#
|
||||
# See https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
|
||||
#
|
||||
# Note:
|
||||
# keybindings needs to have a multiple of two elements
|
||||
# keybindings = [
|
||||
# 0x10, 0xA0,
|
||||
# 0x11, 0xA2,
|
||||
# 0x12, 0xA4,
|
||||
# 0x4A, 0x4B
|
||||
# ]
|
||||
|
||||
# How long to wait in milliseconds for data from moonlight before shutting down the stream
|
||||
# ping_timeout = 10000
|
||||
|
||||
# The file where configuration for the different applications that Sunshine can run during a stream
|
||||
file_apps = apps.json
|
||||
|
||||
# Percentage of error correcting packets per data packet in each video frame
|
||||
# Higher values can correct for more network packet loss, but at the cost of increasing bandwidth usage
|
||||
# The default value of 20 is what GeForce Experience uses
|
||||
#
|
||||
# The value must be greater than 0 and lower than or equal to 255
|
||||
# fec_percentage = 20
|
||||
|
||||
# When multicasting, it could be usefull to have different configurations for each connected Client.
|
||||
# For example:
|
||||
# Clients connected through WAN and LAN have different bitrate contstraints.
|
||||
# Decoders may require different settings for color
|
||||
#
|
||||
# Unlike simply broadcasting to multiple Client, this will generate distinct video streams.
|
||||
# Note, CPU usage increases for each distinct video stream generated
|
||||
channels = 2
|
||||
|
||||
# The back/select button on the controller
|
||||
# On the Shield, the home and powerbutton are not passed to Moonlight
|
||||
# If, after the timeout, the back button is still pressed down, Home/Guide button press is emulated.
|
||||
# If back_button_timeout < 0, then the Home/Guide button will not be emulated
|
||||
# back_button_timeout = 2000
|
||||
|
||||
# !! Windows only !!
|
||||
# Gamepads supported by Sunshine
|
||||
# Possible values:
|
||||
# x360 -- xbox 360 controller
|
||||
# ds4 -- dualshock controller (PS4)
|
||||
# gamepad = x360
|
||||
|
||||
# Control how fast keys will repeat themselves
|
||||
# The initial delay in milliseconds before repeating keys
|
||||
# key_repeat_delay = 500
|
||||
#
|
||||
# How often keys repeat every second
|
||||
# This configurable option supports decimals
|
||||
# key_repeat_frequency = 24.9
|
||||
|
||||
# The name of the audio sink used for Audio Loopback
|
||||
# If you do not specify this variable, pulseaudio will select the default monitor device.
|
||||
#
|
||||
# You can find the name of the audio sink using the following command:
|
||||
# !! Linux only !!
|
||||
# pacmd list-sinks | grep "name:" if running vanilla pulseaudio
|
||||
# pPipewire: Use `pactl info | grep Source`. In some causes you'd need to use the `sink` device. Try `pactl info | grep Sink`, if _Source_ doesn't work
|
||||
# audio_sink = alsa_output.pci-0000_09_00.3.analog-stereo
|
||||
#
|
||||
# !! Windows only !!
|
||||
# tools\audio-info.exe
|
||||
# audio_sink = {0.0.0.00000000}.{FD47D9CC-4218-4135-9CE2-0C195C87405B}
|
||||
#
|
||||
# The virtual sink, is the audio device that's virtual (Like Steam Streaming Speakers), it allows Sunshine
|
||||
# to stream audio, while muting the speakers.
|
||||
# virtual_sink = {0.0.0.00000000}.{8edba70c-1125-467c-b89c-15da389bc1d4}
|
||||
|
||||
# !! Windows only !!
|
||||
# You can select the video card you want to stream:
|
||||
# The appropriate values can be found using the following command:
|
||||
# tools\dxgi-info.exe
|
||||
# adapter_name = Radeon RX 580 Series
|
||||
# output_name = \\.\DISPLAY1
|
||||
|
||||
# !! Linux only !!
|
||||
# Set the display number to stream.
|
||||
# You can find them by the following command:
|
||||
# xrandr --listmonitors
|
||||
# Example output: "0: +HDMI-1 1920/518x1200/324+0+0 HDMI-1"
|
||||
# ^ <-- You need this.
|
||||
# output_name = 0
|
||||
|
||||
###############################################
|
||||
# FFmpeg software encoding parameters
|
||||
# Honestly, I have no idea what the optimal values would be.
|
||||
# Play around with this :)
|
||||
|
||||
# Quantitization Parameter
|
||||
# Some devices don't support Constant Bit Rate. For those devices, QP is used instead
|
||||
# Higher value means more compression, but less quality
|
||||
# qp = 28
|
||||
|
||||
# Minimum number of threads used by ffmpeg to encode the video.
|
||||
# Increasing the value slightly reduces encoding efficiency, but the tradeoff is usually
|
||||
# worth it to gain the use of more CPU cores for encoding. The ideal value is the lowest
|
||||
# value that can reliably encode at your desired streaming settings on your hardware.
|
||||
# min_threads = 1
|
||||
|
||||
# Allows the client to request HEVC Main or HEVC Main10 video streams.
|
||||
# HEVC is more CPU-intensive to encode, so enabling this may reduce performance when using software encoding.
|
||||
# If set to 0 (default), Sunshine will specify support for HEVC based on encoder
|
||||
# If set to 1, Sunshine will not advertise support for HEVC
|
||||
# If set to 2, Sunshine will advertise support for HEVC Main profile
|
||||
# If set to 3, Sunshine will advertise support for HEVC Main and Main10 (HDR) profiles
|
||||
# hevc_mode = 2
|
||||
|
||||
# Force a specific encoder, otherwise Sunshine will use the first encoder that is available
|
||||
# supported encoders:
|
||||
# nvenc
|
||||
# amdvce # NOTE: alpha stage. The cursor is not yet displayed
|
||||
# software
|
||||
#
|
||||
# encoder = software
|
||||
##################################### Software #####################################
|
||||
# See x264 --fullhelp for the different presets
|
||||
# sw_preset = superfast
|
||||
# sw_tune = zerolatency
|
||||
#
|
||||
|
||||
##################################### NVENC #####################################
|
||||
###### presets ###########
|
||||
# default
|
||||
# hp -- high performance
|
||||
# hq -- high quality
|
||||
# slow -- hq 2 passes
|
||||
# medium -- hq 1 pass
|
||||
# fast -- hp 1 pass
|
||||
# bd
|
||||
# ll -- low latency
|
||||
# llhq
|
||||
# llhp
|
||||
# lossless
|
||||
# losslesshp
|
||||
##########################
|
||||
# nv_preset = llhq
|
||||
#
|
||||
####### rate control #####
|
||||
# auto -- let ffmpeg decide rate control
|
||||
# constqp -- constant QP mode
|
||||
# vbr -- variable bitrate
|
||||
# cbr -- constant bitrate
|
||||
# cbr_hq -- cbr high quality
|
||||
# cbr_ld_hq -- cbr low delay high quality
|
||||
# vbr_hq -- vbr high quality
|
||||
##########################
|
||||
# nv_rc = auto
|
||||
|
||||
###### h264 entropy ######
|
||||
# auto -- let ffmpeg nvenc decide the entropy encoding
|
||||
# cabac
|
||||
# cavlc
|
||||
##########################
|
||||
# nv_coder = auto
|
||||
|
||||
##################################### AMD #####################################
|
||||
###### presets ###########
|
||||
# default
|
||||
# speed
|
||||
# balanced
|
||||
##########################
|
||||
# amd_preset = balanced
|
||||
#
|
||||
####### rate control #####
|
||||
# auto -- let ffmpeg decide rate control
|
||||
# constqp -- constant QP mode
|
||||
# vbr_latency -- Latency Constrained Variable Bitrate
|
||||
# vbr_peak -- Peak Contrained Variable Bitrate
|
||||
# cbr -- constant bitrate
|
||||
##########################
|
||||
# amd_rc = auto
|
||||
|
||||
###### h264 entropy ######
|
||||
# auto -- let ffmpeg nvenc decide the entropy encoding
|
||||
# cabac
|
||||
# cavlc
|
||||
##########################
|
||||
# amd_coder = auto
|
||||
|
||||
#################################### VAAPI ###################################
|
||||
####### adapter ##########
|
||||
# Unlike with `amdvce` and `nvenc`, it doesn't matter if video encoding is done
|
||||
# on a different GPU.
|
||||
# Run the following commands:
|
||||
# 1. ls /dev/dri/renderD*
|
||||
# to find all devices capable of VAAPI
|
||||
# 2. vainfo --display drm --device /dev/dri/renderD129 | grep -E "((VAProfileH264High|VAProfileHEVCMain|VAProfileHEVCMain10).*VAEntrypointEncSlice)|Driver version"
|
||||
# Lists the name and capabilities of the device.
|
||||
# To be supported by Sunshine, it needs to have at the very minimum:
|
||||
# VAProfileH264High : VAEntrypointEncSlice
|
||||
# adapter_name = /dev/dri/renderD128
|
||||
|
||||
##############################################
|
||||
# Some configurable parameters, are merely toggles for specific features
|
||||
# The first occurrence turns it on, the second occurence turns it off, the third occurence turns it on again, etc, etc
|
||||
# Here, you change the default state of any flag
|
||||
#
|
||||
# To set the initial state of flags -0 and -1 to on, set the following flags:
|
||||
# flags = 012
|
||||
#
|
||||
# See: sunshine --help for all options under the header: flags
|
||||
23
overlay/templates/xorg/xorg.dummy.conf
Normal file
@@ -0,0 +1,23 @@
|
||||
Section "Device"
|
||||
Identifier "Configured Video Device"
|
||||
Driver "dummy"
|
||||
VideoRam 256000
|
||||
EndSection
|
||||
|
||||
Section "Monitor"
|
||||
Identifier "Configured Monitor"
|
||||
HorizSync 5.0 - 1000.0
|
||||
VertRefresh 5.0 - 200.0
|
||||
ModeLine "1920x1080" 148.50 1920 2448 2492 2640 1080 1084 1089 1125 +Hsync +Vsync
|
||||
EndSection
|
||||
|
||||
Section "Screen"
|
||||
Identifier "Default Screen"
|
||||
Monitor "Configured Monitor"
|
||||
Device "Configured Video Device"
|
||||
DefaultDepth 24
|
||||
SubSection "Display"
|
||||
Depth 24
|
||||
Modes "1920x1080" "1280x800" "1024x768" "1920x1080" "1600x900" "1440x900"
|
||||
EndSubSection
|
||||
EndSection
|
||||
104
overlay/usr/bin/common-functions.sh
Executable file
@@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env bash
|
||||
###
|
||||
# File: common-functions.sh
|
||||
# Project: bin
|
||||
# File Created: Tuesday, 6th October 2022 9:30:00 pm
|
||||
# Author: Josh.5 (jsunnex@gmail.com)
|
||||
# -----
|
||||
# Last Modified: Tuesday, 6th October 2022 9:30:00 pm
|
||||
# Modified By: Josh.5 (jsunnex@gmail.com)
|
||||
###
|
||||
|
||||
# Wait for X server to start
|
||||
# (Credit: https://gist.github.com/tullmann/476cc71169295d5c3fe6)
|
||||
wait_for_x() {
|
||||
MAX=60 # About 30 seconds
|
||||
CT=0
|
||||
while ! xdpyinfo >/dev/null 2>&1; do
|
||||
sleep 0.50s
|
||||
CT=$(( CT + 1 ))
|
||||
if [ "$CT" -ge "$MAX" ]; then
|
||||
echo "FATAL: $0: Gave up waiting for X server $DISPLAY"
|
||||
exit 11
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Wait for udev init to complete
|
||||
wait_for_udev() {
|
||||
MAX=10
|
||||
CT=0
|
||||
while [ ! -f /tmp/.started-udev ]; do
|
||||
sleep 1
|
||||
CT=$(( CT + 1 ))
|
||||
if [ "$CT" -ge "$MAX" ]; then
|
||||
echo "FATAL: $0: Gave up waiting for udev server to start"
|
||||
exit 11
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Wait for dockerd to start
|
||||
wait_for_docker() {
|
||||
MAX=10
|
||||
CT=0
|
||||
while ! docker system info >/dev/null 2>&1; do
|
||||
sleep 1
|
||||
CT=$(( CT + 1 ))
|
||||
if [ "$CT" -ge "$MAX" ]; then
|
||||
echo "FATAL: $0: Gave up waiting for dockerd service to start"
|
||||
exit 11
|
||||
fi
|
||||
done
|
||||
echo "DOCKERD RUNNING!"
|
||||
}
|
||||
|
||||
# Wait for desktop to start
|
||||
wait_for_desktop() {
|
||||
MAX=30
|
||||
CT=0
|
||||
while [ ! -f /tmp/.started-desktop ]; do
|
||||
sleep 1
|
||||
CT=$(( CT + 1 ))
|
||||
if [ "$CT" -ge "$MAX" ]; then
|
||||
echo "FATAL: $0: Gave up waiting for Desktop to start"
|
||||
exit 11
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Fech NVIDIA GPU device (if one exists)
|
||||
get_nvidia_gpu_id() {
|
||||
if [ "${NVIDIA_VISIBLE_DEVICES:-}" == "all" ]; then
|
||||
gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2> /dev/null | sed -n 2p)
|
||||
elif [ -z "${NVIDIA_VISIBLE_DEVICES:-}" ]; then
|
||||
gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2> /dev/null | sed -n 2p)
|
||||
else
|
||||
gpu_select=$(nvidia-smi --format=csv --id=$(echo "${NVIDIA_VISIBLE_DEVICES:-}" | cut -d ',' -f1) --query-gpu=uuid | sed -n 2p)
|
||||
if [ -z "$gpu_select" ]; then
|
||||
gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2> /dev/null | sed -n 2p)
|
||||
fi
|
||||
fi
|
||||
echo ${gpu_select}
|
||||
}
|
||||
|
||||
export_desktop_dbus_session() {
|
||||
if [ ! -f /tmp/.dbus-desktop-session.env ]; then
|
||||
echo "$(dbus-launch)" > /tmp/.dbus-desktop-session.env
|
||||
fi
|
||||
export $(cat /tmp/.dbus-desktop-session.env)
|
||||
}
|
||||
|
||||
# Wait for desktop dbus session to start
|
||||
wait_for_desktop_dbus_session() {
|
||||
MAX=10
|
||||
CT=0
|
||||
while [ ! -f /tmp/.dbus-desktop-session.env ]; do
|
||||
sleep 1
|
||||
CT=$(( CT + 1 ))
|
||||
if [ "$CT" -ge "$MAX" ]; then
|
||||
echo "FATAL: $0: Gave up waiting for Desktop dbus-launch session to be created"
|
||||
exit 11
|
||||
fi
|
||||
done
|
||||
}
|
||||
16
overlay/usr/bin/drop_caches.sh
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
###
|
||||
# File: drop_caches.sh
|
||||
# Project: docker-steam-headless
|
||||
# File Created: Wednesday, 12th January 2022 5:08:46 pm
|
||||
# Author: Josh.5 (jsunnex@gmail.com)
|
||||
# -----
|
||||
# Last Modified: Wednesday, 12th January 2022 5:44:17 pm
|
||||
# Modified By: Josh.5 (jsunnex@gmail.com)
|
||||
###
|
||||
|
||||
# Clear out the memory page cache
|
||||
echo 1 > /proc/sys/vm/drop_caches
|
||||
|
||||
# Flush any FS buffers
|
||||
sync
|
||||
31
overlay/usr/bin/install_firefox.sh
Executable file
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "**** Installing/upgrading Firefox via flatpak ****"
|
||||
|
||||
# Install Firefox
|
||||
flatpak --user remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
|
||||
flatpak --user install --assumeyes --or-update flathub org.mozilla.firefox
|
||||
|
||||
# Configure Firefox as the default browser
|
||||
echo "Configure Firefox..."
|
||||
custom_webbrowser="$(cat <<EOF
|
||||
"libraryfolders"
|
||||
[Desktop Entry]
|
||||
NoDisplay=true
|
||||
Version=1.0
|
||||
Encoding=UTF-8
|
||||
Type=X-XFCE-Helper
|
||||
X-XFCE-Category=WebBrowser
|
||||
X-XFCE-CommandsWithParameter=${USER_HOME:?}/.local/share/flatpak/exports/bin/org.mozilla.firefox "%s"
|
||||
Icon=org.mozilla.firefox
|
||||
Name=org.mozilla.firefox
|
||||
X-XFCE-Commands=${USER_HOME:?}/.local/share/flatpak/exports/bin/org.mozilla.firefox
|
||||
EOF
|
||||
)"
|
||||
if [[ ! -f "${USER_HOME:?}/.local/share/xfce4/helpers/custom-WebBrowser.desktop" ]]; then
|
||||
mkdir -p "${USER_HOME:?}/.local/share/xfce4/helpers"
|
||||
echo "${custom_webbrowser}" > "${USER_HOME:?}/.local/share/xfce4/helpers/custom-WebBrowser.desktop"
|
||||
gio mime x-scheme-handler/http org.mozilla.firefox.desktop
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
14
overlay/usr/bin/install_flatseal.sh
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "**** Installing/upgrading Flatseal via flatpak ****"
|
||||
|
||||
# Install Flatseal
|
||||
flatpak --user remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
|
||||
flatpak --user install --assumeyes --or-update com.github.tchx84.Flatseal
|
||||
|
||||
# Configure Flatseal
|
||||
echo "Configure Flatseal..."
|
||||
sed -i 's/^Categories=.*$/Categories=Utility;/' \
|
||||
${USER_HOME}/.local/share/flatpak/exports/share/applications/com.github.tchx84.Flatseal.desktop
|
||||
|
||||
echo "DONE"
|
||||
14
overlay/usr/bin/install_protonup.sh
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "**** Installing/upgrading ProtonUp-Qt via flatpak ****"
|
||||
|
||||
# Install ProtonUp-Qt
|
||||
flatpak --user remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
|
||||
flatpak --user install --assumeyes --or-update net.davidotek.pupgui2
|
||||
|
||||
# Configure ProtonUp-Qt
|
||||
echo "Configure ProtonUp-Qt..."
|
||||
sed -i 's/^Categories=.*$/Categories=Utility;/' \
|
||||
${USER_HOME}/.local/share/flatpak/exports/share/applications/net.davidotek.pupgui2.desktop
|
||||
|
||||
echo "DONE"
|
||||
53
overlay/usr/bin/start-desktop.sh
Executable file
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env bash
|
||||
###
|
||||
# File: start-desktop.sh
|
||||
# Project: bin
|
||||
# File Created: Thursday, 1st January 1970 12:00:00 pm
|
||||
# Author: Console and webGui login account (jsunnex@gmail.com)
|
||||
# -----
|
||||
# Last Modified: Saturday, 8th July 2023 6:16:47 pm
|
||||
# Modified By: Console and webGui login account (jsunnex@gmail.com)
|
||||
###
|
||||
set -e
|
||||
source /usr/bin/common-functions.sh
|
||||
|
||||
# CATCH TERM SIGNAL:
|
||||
_term() {
|
||||
kill -TERM "$desktop_pid" 2>/dev/null
|
||||
}
|
||||
trap _term SIGTERM SIGINT
|
||||
|
||||
|
||||
# CONFIGURE:
|
||||
# Remove lockfile
|
||||
rm -f /tmp/.started-desktop
|
||||
# Start a session bus instance of dbus-daemon
|
||||
# Note: This script should be the only one that waits for X after exporting this dbus session
|
||||
rm -fv /tmp/.dbus-desktop-session.env
|
||||
export_desktop_dbus_session
|
||||
# Configure some XDG environment variables
|
||||
export XDG_CACHE_HOME="${USER_HOME:?}/.cache"
|
||||
export XDG_CONFIG_HOME="${USER_HOME:?}/.config"
|
||||
export XDG_DATA_HOME="${USER_HOME:?}/.local/share"
|
||||
|
||||
# EXECUTE PROCESS:
|
||||
# Wait for the X server to start
|
||||
wait_for_x
|
||||
# Install/Upgrade user apps
|
||||
if [[ ! -f /tmp/.desktop-apps-updated ]]; then
|
||||
xterm -geometry 200x50+0+0 -ls -e /bin/bash -c "
|
||||
source /usr/bin/install_firefox.sh;
|
||||
source /usr/bin/install_protonup.sh;
|
||||
sleep 1;
|
||||
"
|
||||
touch /tmp/.desktop-apps-updated
|
||||
fi
|
||||
|
||||
# Run the desktop environment
|
||||
echo "**** Starting Xfce4 ****"
|
||||
/usr/bin/startxfce4 &
|
||||
desktop_pid=$!
|
||||
touch /tmp/.started-desktop
|
||||
|
||||
# WAIT FOR CHILD PROCESS:
|
||||
wait "$desktop_pid"
|
||||
29
overlay/usr/bin/start-pulseaudio.sh
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env bash
|
||||
###
|
||||
# File: start-desktop.sh
|
||||
# Project: bin
|
||||
# File Created: Thursday, 1st January 1970 12:00:00 pm
|
||||
# Author: Josh.5 (jsunnex@gmail.com)
|
||||
# -----
|
||||
# Last Modified: Sunday, 2nd October 2022 22:58:17 pm
|
||||
# Modified By: Josh.5 (jsunnex@gmail.com)
|
||||
###
|
||||
set -e
|
||||
|
||||
# CATCH TERM SIGNAL:
|
||||
_term() {
|
||||
kill -TERM "$pulseaudio_pid" 2>/dev/null
|
||||
}
|
||||
trap _term SIGTERM SIGINT
|
||||
|
||||
|
||||
# EXECUTE PROCESS:
|
||||
echo "PULSEAUDIO: Starting pulseaudio service"
|
||||
sleep 5
|
||||
#/usr/bin/pulseaudio --disallow-module-loading --disallow-exit --exit-idle-time=-1 &
|
||||
/usr/bin/pulseaudio --exit-idle-time=-1 &
|
||||
pulseaudio_pid=$!
|
||||
|
||||
|
||||
# WAIT FOR CHILD PROCESS:
|
||||
wait "$pulseaudio_pid"
|
||||
75
overlay/usr/bin/start-sunshine.sh
Executable file
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env bash
|
||||
###
|
||||
# File: start-sunshine.sh
|
||||
# Project: bin
|
||||
# File Created: Tuesday, 4th October 2022 8:22:17 pm
|
||||
# Author: Josh.5 (jsunnex@gmail.com)
|
||||
# -----
|
||||
# Last Modified: Tuesday, 4th October 2022 8:22:17 pm
|
||||
# Modified By: Josh.5 (jsunnex@gmail.com)
|
||||
###
|
||||
set -e
|
||||
source /usr/bin/common-functions.sh
|
||||
|
||||
# CATCH TERM SIGNAL:
|
||||
_term() {
|
||||
kill -INT "$sunshine_pid" 2>/dev/null
|
||||
sleep 0.5
|
||||
counter=0
|
||||
while kill -0 "$sunshine_pid"; do
|
||||
kill -TERM "$sunshine_pid" 2>/dev/null
|
||||
counter=$((counter + 1))
|
||||
[ "$counter" -gt 2 ] && break
|
||||
sleep 2
|
||||
done
|
||||
counter=0
|
||||
while kill -0 "$sunshine_pid"; do
|
||||
kill -KILL "$sunshine_pid" 2>/dev/null
|
||||
counter=$((counter + 1))
|
||||
[ "$counter" -gt 2 ] && break
|
||||
sleep 1
|
||||
done
|
||||
}
|
||||
trap _term SIGTERM SIGINT
|
||||
|
||||
|
||||
# CONFIGURE:
|
||||
# Install default configurations
|
||||
mkdir -p "${USER_HOME:?}/.config/sunshine"
|
||||
if [ ! -f "${USER_HOME:?}/.config/sunshine/sunshine.conf" ]; then
|
||||
cp -vf /templates/sunshine/sunshine.conf "${USER_HOME:?}/.config/sunshine/sunshine.conf"
|
||||
fi
|
||||
if [ ! -f "${USER_HOME:?}/.config/sunshine/apps.json" ]; then
|
||||
cp -vf /templates/sunshine/apps.json "${USER_HOME:?}/.config/sunshine/apps.json"
|
||||
fi
|
||||
if [ ! -f "${USER_HOME:?}/.config/sunshine/sunshine_state.json" ]; then
|
||||
echo "{}" > "${USER_HOME:?}/.config/sunshine/sunshine_state.json"
|
||||
fi
|
||||
# Reset the default username/password
|
||||
if ([ "X${SUNSHINE_USER:-}" != "X" ] && [ "X${SUNSHINE_PASS:-}" != "X" ]); then
|
||||
/usr/bin/sunshine "${USER_HOME:?}/.config/sunshine/sunshine.conf" --creds "${SUNSHINE_USER:?}" "${SUNSHINE_PASS:?}"
|
||||
fi
|
||||
# Remove any auto-start scripts from user's .local dir
|
||||
if [ -f "${USER_HOME:?}/.config/autostart/Sunshine.desktop" ]; then
|
||||
rm -fv "${USER_HOME:?}/.config/autostart/Sunshine.desktop"
|
||||
fi
|
||||
|
||||
|
||||
# EXECUTE PROCESS:
|
||||
# Wait for the X server to start
|
||||
wait_for_x
|
||||
|
||||
# Start a session bus instance of dbus-daemon
|
||||
wait_for_desktop_dbus_session
|
||||
export_desktop_dbus_session
|
||||
|
||||
# Wait for the desktop to start
|
||||
wait_for_desktop
|
||||
|
||||
# Start the sunshine server
|
||||
/usr/bin/dumb-init /usr/bin/sunshine "${USER_HOME:?}/.config/sunshine/sunshine.conf" &
|
||||
sunshine_pid=$!
|
||||
|
||||
|
||||
# WAIT FOR CHILD PROCESS:
|
||||
wait "$sunshine_pid"
|
||||
43
overlay/usr/bin/start-udev.sh
Executable file
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env bash
|
||||
###
|
||||
# File: start-udev.sh
|
||||
# Project: bin
|
||||
# File Created: Tuesday, 12th January 2022 8:46:47 am
|
||||
# Author: Josh.5 (jsunnex@gmail.com)
|
||||
# -----
|
||||
# Last Modified: Friday, 14th January 2022 9:21:00 am
|
||||
# Modified By: Josh.5 (jsunnex@gmail.com)
|
||||
###
|
||||
set -e
|
||||
|
||||
# CATCH TERM SIGNAL:
|
||||
_term() {
|
||||
kill -TERM "$monitor_pid" 2>/dev/null
|
||||
}
|
||||
trap _term SIGTERM SIGINT
|
||||
|
||||
|
||||
# CONFIGURE:
|
||||
# Remove lockfile
|
||||
rm -f /tmp/.started-udev
|
||||
|
||||
|
||||
# EXECUTE PROCESS:
|
||||
# Start udev
|
||||
if command -v udevd &>/dev/null; then
|
||||
unshare --net udevd --daemon &>/dev/null
|
||||
else
|
||||
unshare --net /lib/systemd/systemd-udevd --daemon &>/dev/null
|
||||
fi
|
||||
# Monitor kernel uevents
|
||||
udevadm monitor &
|
||||
monitor_pid=$!
|
||||
# Touch lockfile
|
||||
sleep 1
|
||||
touch /tmp/.started-udev
|
||||
# Wait for 10 seconds, then request device events from the kernel
|
||||
sleep 10
|
||||
udevadm trigger
|
||||
|
||||
# WAIT FOR CHILD PROCESS:
|
||||
wait "$monitor_pid"
|
||||
30
overlay/usr/bin/start-x11vnc.sh
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env bash
|
||||
###
|
||||
# File: start-x11vnc.sh
|
||||
# Project: bin
|
||||
# File Created: Tuesday, 6th October 2022 9:30:00 pm
|
||||
# Author: Josh.5 (jsunnex@gmail.com)
|
||||
# -----
|
||||
# Last Modified: Tuesday, 6th October 2022 9:30:00 pm
|
||||
# Modified By: Josh.5 (jsunnex@gmail.com)
|
||||
###
|
||||
set -e
|
||||
source /usr/bin/common-functions.sh
|
||||
|
||||
# CATCH TERM SIGNAL:
|
||||
_term() {
|
||||
kill -TERM "$x11vnc_pid" 2>/dev/null
|
||||
}
|
||||
trap _term SIGTERM SIGINT
|
||||
|
||||
|
||||
# EXECUTE PROCESS:
|
||||
# Wait for the X server to start
|
||||
wait_for_x
|
||||
# Start the x11vnc server
|
||||
/usr/bin/x11vnc -display ${DISPLAY} -rfbport ${PORT_VNC} -shared -forever&
|
||||
x11vnc_pid=$!
|
||||
|
||||
|
||||
# WAIT FOR CHILD PROCESS:
|
||||
wait "$x11vnc_pid"
|
||||
52
overlay/usr/bin/start-xorg.sh
Executable file
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env bash
|
||||
###
|
||||
# File: start-xorg.sh
|
||||
# Project: bin
|
||||
# File Created: Tuesday, 11th January 2022 8:28:52 pm
|
||||
# Author: Josh.5 (jsunnex@gmail.com)
|
||||
# -----
|
||||
# Last Modified: Friday, 6th October 2022 9:21:00 pm
|
||||
# Modified By: Josh.5 (jsunnex@gmail.com)
|
||||
###
|
||||
set -e
|
||||
source /usr/bin/common-functions.sh
|
||||
|
||||
# CATCH TERM SIGNAL:
|
||||
_term() {
|
||||
kill -TERM "$xorg_pid" 2>/dev/null
|
||||
}
|
||||
trap _term SIGTERM SIGINT
|
||||
|
||||
|
||||
# EXECUTE PROCESS:
|
||||
# Wait for udev
|
||||
if [ $(grep autostart /etc/supervisor.d/udev.ini 2> /dev/null) == "autostart=true" ]; then
|
||||
wait_for_udev
|
||||
fi
|
||||
# Run X server
|
||||
/usr/bin/Xorg \
|
||||
-ac \
|
||||
-noreset \
|
||||
-novtswitch \
|
||||
-sharevts \
|
||||
+extension RANDR \
|
||||
+extension RENDER \
|
||||
+extension GLX \
|
||||
+extension XVideo \
|
||||
+extension DOUBLE-BUFFER \
|
||||
+extension SECURITY \
|
||||
+extension DAMAGE \
|
||||
+extension X-Resource \
|
||||
-extension XINERAMA -xinerama \
|
||||
+extension Composite +extension COMPOSITE \
|
||||
-dpms \
|
||||
-s off \
|
||||
-nolisten tcp \
|
||||
-iglx \
|
||||
-verbose \
|
||||
vt7 "${DISPLAY:?}" &
|
||||
xorg_pid=$!
|
||||
|
||||
|
||||
# WAIT FOR CHILD PROCESS:
|
||||
wait "$xorg_pid"
|
||||
84
overlay/usr/bin/steam-headless-wol-power-manager
Executable file
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env bash
|
||||
###
|
||||
# File: steam-headless-wol-power-manager
|
||||
# Project: bin
|
||||
# File Created: Tuesday, 5th September 2023 5:35:38 pm
|
||||
# Author: Josh.5 (jsunnex@gmail.com)
|
||||
# -----
|
||||
# Last Modified: Tuesday, 5th September 2023 5:35:38 pm
|
||||
# Modified By: Josh.5 (jsunnex@gmail.com)
|
||||
###
|
||||
set -e
|
||||
|
||||
# Function to execute restart to WoL monitor
|
||||
restart_to_wol_monitor() {
|
||||
# Create WoL monitor lock file. This will be read during the next restart and will trigger a singluar WoL monitor service.
|
||||
touch /tmp/.wol-monitor
|
||||
|
||||
# Stop all processes inside the container by sending a SIGINT to the main supervisord process (PID 1)
|
||||
kill -2 1
|
||||
|
||||
# Exit script
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Function to execute restart to Desktop
|
||||
restart_to_desktop_mode() {
|
||||
# Remove WoL monitor lock file.
|
||||
rm -f /tmp/.wol-monitor
|
||||
|
||||
# Stop all processes inside the container by sending a SIGINT to the main supervisord process (PID 1)
|
||||
kill -2 1
|
||||
|
||||
# Exit script
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Function to monitor for no user input
|
||||
start_idle_monitor() {
|
||||
# Set the idle timeout in milliseconds (60 minutes = 3600000 milliseconds)
|
||||
local idle_timeout=3600000
|
||||
|
||||
# Monitor input. After an hour of no input
|
||||
echo "Starting idle inputs monitor service..."
|
||||
while true; do
|
||||
# Sleep for a short interval (e.g., 1 minute) before checking
|
||||
sleep 60
|
||||
|
||||
# Get the current idle time in milliseconds using xprintidle
|
||||
idle_time=$(xprintidle)
|
||||
|
||||
# Check if the idle time exceeds the specified timeout
|
||||
if [ "${idle_time:?}" -ge "${idle_timeout:?}" ]; then
|
||||
# TODO: Check if any sessions exist in sunshine
|
||||
|
||||
# Execute restart to WoL monitor function
|
||||
echo "No user activity for over 60 minutes. Entering WoL Monitor Mode."
|
||||
restart_to_wol_monitor
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Function to monitor for WoL events
|
||||
start_wol_monitor() {
|
||||
# Specify port to listen to (9 is the default WoL port).
|
||||
listen_port=9
|
||||
|
||||
# Start the WoL monitor service
|
||||
echo "Starting WoL monitor service..."
|
||||
|
||||
while true; do
|
||||
# Listen for WoL magic packets on the specified port
|
||||
tcpdump -i any -n -l -c 1 -q "udp port $listen_port and (udp[8:4] = 0xFFFFFFFF)"
|
||||
|
||||
# Execute restart to desktop function
|
||||
echo "WoL event received. Entering Desktop Mode."
|
||||
restart_to_desktop_mode
|
||||
done
|
||||
}
|
||||
|
||||
if [ -f "/tmp/.wol-monitor" ]; then
|
||||
start_wol_monitor
|
||||
else
|
||||
start_idle_monitor
|
||||
fi
|
||||
158
overlay/usr/bin/sunshine-run
Executable file
@@ -0,0 +1,158 @@
|
||||
#!/usr/bin/env bash
|
||||
###
|
||||
# File: sunshine-run
|
||||
# Project: bin
|
||||
# File Created: Tuesday, 23rd August 2023 3:28:52 pm
|
||||
# Author: Josh.5 (jsunnex@gmail.com)
|
||||
# -----
|
||||
# Last Modified: Friday, 23rd August 2023 4:21:00 pm
|
||||
# Modified By: Josh.5 (jsunnex@gmail.com)
|
||||
###
|
||||
set -e
|
||||
|
||||
exec >> >(tee -a ${USER_HOME:?}/.cache/log/sunshine_run.log) 2>&1
|
||||
echo
|
||||
echo "-------------------------------"
|
||||
echo
|
||||
date
|
||||
echo
|
||||
echo "-------------------------------"
|
||||
echo
|
||||
echo "**** Execute sunshine-run ****"
|
||||
echo
|
||||
|
||||
# Trap SIGINT, SIGQUIT, SIGHUP, SIGTERM to forward signals to the child process
|
||||
_term() {
|
||||
if [ -n "${proc_pid}" ]; then
|
||||
# Read all child processes of proc_pid first
|
||||
child_pids=$(pgrep -P $proc_pid)
|
||||
# Forward the signal proc_pid
|
||||
echo " - Checking for status of main process ${proc_pid}"
|
||||
if kill -0 "${proc_pid}" 2>/dev/null; then
|
||||
echo " - Forwarding signal $1 to process ${proc_pid}"
|
||||
kill -s "${1}" "${proc_pid}"
|
||||
else
|
||||
echo " - Process ${proc_pid} is already stopped. Nothing to do here."
|
||||
fi
|
||||
for child_pid in ${child_pids:-}; do
|
||||
echo " - Checking for status of child process ${child_pid}"
|
||||
if kill -0 "${child_pid}" 2>/dev/null; then
|
||||
echo " - Forwarding signal $1 to process ${child_pid}"
|
||||
kill -s "${1}" "${child_pid}"
|
||||
else
|
||||
echo " - Process ${child_pid} is already stopped. Nothing to do here."
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
trap '_term INT' SIGINT
|
||||
trap '_term QUIT' SIGQUIT
|
||||
trap '_term HUP' SIGHUP
|
||||
trap '_term TERM' SIGTERM
|
||||
|
||||
# Record sunshine-run PID
|
||||
echo " - Recording sunshine-run PID '$$' in /tmp/sunshine-exec-run.pid"
|
||||
echo "$$" > /tmp/sunshine-exec-run.pid
|
||||
|
||||
# Wipe session config
|
||||
echo "" > /tmp/sunshine-exec-run.conf
|
||||
|
||||
# Update display resolution and refresh reate if client provided the required details
|
||||
if ([ "X${SUNSHINE_CLIENT_WIDTH:-}" != "X" ] && [ "X${SUNSHINE_CLIENT_HEIGHT:-}" != "X" ] && [ "X${SUNSHINE_CLIENT_FPS:-}" != "X" ]); then
|
||||
# Don't fail script if something goes wrong here. Set +e in subprocess
|
||||
(
|
||||
set +e
|
||||
echo " - Setting display resolution to ${SUNSHINE_CLIENT_WIDTH:?}x${SUNSHINE_CLIENT_HEIGHT:?} ${SUNSHINE_CLIENT_FPS:?}Hz"
|
||||
|
||||
# Read current display mode and extract resolution and refresh rate from the mode string
|
||||
__xrandr_out="$(xrandr -q)"
|
||||
__current_current_mode=$(echo "${__xrandr_out:?}" | awk '/\*/ {print $0}')
|
||||
__current_resolution=$(echo ${__current_current_mode:?} | awk '{print $1}')
|
||||
__current_refresh_rate=$(echo ${__current_current_mode:?} | awk '{sub(/\*/, "", $2); print $2}')
|
||||
|
||||
# Get the primary output device
|
||||
__primary_output="$(echo "${__xrandr_out:?}" | grep primary | awk '{print $1}')"
|
||||
|
||||
# Get the modeline from cvt and extract the second line (which contains the modeline)
|
||||
__client_modeline=$(cvt "${SUNSHINE_CLIENT_WIDTH:?}" "${SUNSHINE_CLIENT_HEIGHT:?}" "${SUNSHINE_CLIENT_FPS:?}" | grep Modeline | sed -e 's/Modeline //')
|
||||
# Create a new mode for this. This allows us to force a set refresh rate that may not be supported by the display
|
||||
__client_mode=$(echo "${__client_modeline:?}" | awk -F '"' '{print $2}')
|
||||
|
||||
# Check if this custom mode is already created
|
||||
if ! echo "${__xrandr_out:?}" | grep -q "${__client_mode:?}"; then
|
||||
# Custom mode does not yet exist. Create it
|
||||
echo " - Adding new mode '${__client_mode:?}' with new modeline '${__client_modeline:?}'"
|
||||
xrandr --newmode "${__client_mode:?}" ${__client_modeline##*\"}
|
||||
if [ $? -gt 0 ]; then
|
||||
echo " - WARNING: Failed to add new mode '${__client_mode:?}'."
|
||||
else
|
||||
echo " - SUCCESS"
|
||||
fi
|
||||
else
|
||||
echo " - Custom mode '${__client_mode:?}' already exists."
|
||||
fi
|
||||
# Check if custom mode exists
|
||||
__xrandr_out="$(xrandr -q)"
|
||||
if echo "${__xrandr_out:?}" | grep -q "${__client_mode:?}"; then
|
||||
# Check if this mode is already added to the primary display
|
||||
if ! echo "${__xrandr_out:?}" | sed -n "/${__primary_output:?}/,/^[^[:space:]]/ {/^[[:space:]]/p}" | grep -q "${__client_mode:?}"; then
|
||||
# Custom mode exists, but is not yet added to the primary output device. Add it
|
||||
echo " - Adding custom mode '${__client_mode:?}' to device '${__primary_output:?}'"
|
||||
xrandr --addmode "${__primary_output:?}" "${__client_mode:?}"
|
||||
__mode_added=$?
|
||||
if [ "${__mode_added:-0}" -gt 0 ]; then
|
||||
echo " - WARNING: Failed to assign custom mode to primary output device '${__primary_output:?}'."
|
||||
else
|
||||
echo " - SUCCESS"
|
||||
fi
|
||||
else
|
||||
echo " - Custom mode '${__client_mode:?}' is already configured for the primary output device."
|
||||
__mode_added=0
|
||||
fi
|
||||
else
|
||||
echo " - WARNING: Custom mode '${__client_mode:?}' does not exist."
|
||||
fi
|
||||
|
||||
# Set the current resoultion to the new mode
|
||||
if ([ "X${__mode_added:-}" = "X" ] || [ "${__mode_added:-0}" -gt 0 ]); then
|
||||
echo " - Attempting to set the display mode to a supported '${SUNSHINE_CLIENT_WIDTH:?}x${SUNSHINE_CLIENT_HEIGHT:?}' mode. Note that this may not support the configured refresh rate."
|
||||
xrandr --output "${__primary_output:?}" --mode ${SUNSHINE_CLIENT_WIDTH:?}x${SUNSHINE_CLIENT_HEIGHT:?} --refresh ${SUNSHINE_CLIENT_FPS:?}
|
||||
if [ $? -gt 0 ]; then
|
||||
echo " - WARNING: Failed to set current output to mode '${SUNSHINE_CLIENT_WIDTH:?}x${SUNSHINE_CLIENT_HEIGHT:?}' on device '${__primary_output:?}'."
|
||||
else
|
||||
echo " - SUCCESS"
|
||||
fi
|
||||
else
|
||||
echo " - Setting the display mode to '${__client_mode:?}'"
|
||||
xrandr --output "${__primary_output:?}" --mode "${__client_mode:?}" --rate "${SUNSHINE_CLIENT_FPS:?}"
|
||||
if [ $? -gt 0 ]; then
|
||||
echo " - WARNING: Failed to set current output to custom mode '${__client_mode:?}' on device '${__primary_output:?}'."
|
||||
else
|
||||
echo " - SUCCESS"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Save original display settings to config file. This will be read and used to restore the original display settings when the client disconnects.
|
||||
echo "primary_output='${__primary_output:?}'" >> /tmp/sunshine-exec-run.conf
|
||||
echo "display_mode='${__current_resolution:?}'" >> /tmp/sunshine-exec-run.conf
|
||||
echo "display_rate='${__current_refresh_rate:?}'" >> /tmp/sunshine-exec-run.conf
|
||||
)
|
||||
fi
|
||||
|
||||
# Run child process
|
||||
/usr/bin/dumb-init "${@}" &
|
||||
proc_pid=$!
|
||||
|
||||
# Wait for child process to exit:
|
||||
echo " - Waiting for PID '${proc_pid}' to exit"
|
||||
wait "$proc_pid"
|
||||
|
||||
# Clean up PID file
|
||||
if [ -f /tmp/sunshine-exec-run.pid ]; then
|
||||
echo " - Removing sunshine-run pidfile."
|
||||
rm -f /tmp/sunshine-exec-run.pid
|
||||
else
|
||||
echo " - WARNING: No sunshine-run pidfile found for removal."
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
110
overlay/usr/bin/sunshine-stop
Executable file
@@ -0,0 +1,110 @@
|
||||
#!/usr/bin/env bash
|
||||
###
|
||||
# File: sunshine-stop
|
||||
# Project: bin
|
||||
# File Created: Tuesday, 23rd August 2023 3:28:52 pm
|
||||
# Author: Josh.5 (jsunnex@gmail.com)
|
||||
# -----
|
||||
# Last Modified: Friday, 23rd August 2023 4:21:00 pm
|
||||
# Modified By: Josh.5 (jsunnex@gmail.com)
|
||||
###
|
||||
set -e
|
||||
|
||||
exec >> >(tee -a ${USER_HOME:?}/.cache/log/sunshine_stop.log) 2>&1
|
||||
echo
|
||||
echo "-------------------------------"
|
||||
echo
|
||||
date
|
||||
echo
|
||||
echo "-------------------------------"
|
||||
echo
|
||||
echo "**** Execute sunshine-stop ****"
|
||||
echo
|
||||
|
||||
# Read the run config
|
||||
if [ -f /tmp/sunshine-exec-run.conf ]; then
|
||||
echo " - Reading sunshine-run config."
|
||||
. /tmp/sunshine-exec-run.conf
|
||||
else
|
||||
echo " - WARNING: No sunshine-run config found for import."
|
||||
fi
|
||||
|
||||
# Read the process PID
|
||||
if [ -f /tmp/sunshine-exec-run.pid ]; then
|
||||
main_process_pid="$(cat /tmp/sunshine-exec-run.pid)"
|
||||
echo " - Found initial sunshine-run PID '${main_process_pid}'."
|
||||
else
|
||||
echo " - WARNING: No sunshine-run PID found."
|
||||
fi
|
||||
|
||||
# Send a INT signal to the PID (if it is found)
|
||||
if [ "X${main_process_pid:-}" != "X" ]; then
|
||||
echo " - Sending SIGINT to PID '${main_process_pid}'."
|
||||
kill -INT "${main_process_pid}" || true
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
# Run a loop to check for any other "sunshine-run" processes and send them also a INT signal
|
||||
echo " - Checking for other sunshine-run processes..."
|
||||
for process_pid in $(ps aux | grep -v grep | grep sunshine-run | awk '{print $2}'); do
|
||||
# Ensure this process is still running
|
||||
if ! kill -0 "$process_pid" 2>/dev/null; then
|
||||
continue
|
||||
fi
|
||||
echo " - Stopping PID '${process_pid}' - $(ps -p ${process_pid} -o command | awk 'NR>1')"
|
||||
# Send this process a SIGINT
|
||||
echo " - Sending SIGINT to PID '${process_pid}'."
|
||||
kill -INT "${process_pid}" 2>/dev/null || true
|
||||
sleep 0.5
|
||||
# Send this process a SIGTERM every 2 seconds util stopped or until it has sent 3 signals
|
||||
counter=0
|
||||
while kill -0 "$process_pid" 2>/dev/null; do
|
||||
echo " - Sending SIGTERM to PID '${process_pid}'."
|
||||
kill -TERM "$process_pid" 2>/dev/null || true
|
||||
counter=$((counter + 1))
|
||||
[ "$counter" -gt 2 ] && break
|
||||
sleep 2
|
||||
done
|
||||
# Send this process a SIGKILL every second until stopped or until it has sent 3 signals
|
||||
counter=0
|
||||
while kill -0 "$process_pid" 2>/dev/null; do
|
||||
echo " - Sending SIGKILL to PID '${process_pid}'."
|
||||
kill -KILL "$process_pid" 2>/dev/null || true
|
||||
counter=$((counter + 1))
|
||||
[ "$counter" -gt 2 ] && break
|
||||
sleep 1
|
||||
done
|
||||
if ! kill -0 "$process_pid" 2>/dev/null; then
|
||||
echo " - PID '${process_pid}' stopped."
|
||||
else
|
||||
echo " - ERROR: Failed to kill PID '${process_pid}'."
|
||||
fi
|
||||
done
|
||||
echo " - All sunshine-run related processes are stopped."
|
||||
|
||||
# Check if the required information was stored for resetting the display resolution and refresh rate
|
||||
if ([ "X${primary_output:-}" != "X" ] && [ "X${display_mode:-}" != "X" ] && [ "X${display_rate:-}" != "X" ]); then
|
||||
# Reset display resolution and refresh rate
|
||||
echo " - Resetting display resolution to ${display_mode:?} ${display_rate:?}Hz"
|
||||
xrandr --output "${primary_output:?}" --mode "${display_mode:?}" --rate "${display_rate:?}"
|
||||
else
|
||||
echo " - WARNING: original display config not found. Resolution will not be reset."
|
||||
fi
|
||||
|
||||
# Clean up config file
|
||||
if [ -f /tmp/sunshine-exec-run.conf ]; then
|
||||
echo " - Removing sunshine-run config."
|
||||
rm -f /tmp/sunshine-exec-run.conf
|
||||
else
|
||||
echo " - WARNING: No sunshine-run config found for removal."
|
||||
fi
|
||||
|
||||
# Clean up PID file
|
||||
if [ -f /tmp/sunshine-exec-run.pid ]; then
|
||||
echo " - Removing sunshine-run pidfile."
|
||||
rm -f /tmp/sunshine-exec-run.pid
|
||||
else
|
||||
echo " - WARNING: No sunshine-run pidfile found for removal."
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
23
overlay/usr/bin/xfce4-close-all-windows
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
###
|
||||
# File: xfce4-close-all-windows
|
||||
# Project: bin
|
||||
# File Created: Tuesday, 22nd August 2023 3:28:52 pm
|
||||
# Author: Josh.5 (jsunnex@gmail.com)
|
||||
# -----
|
||||
# Last Modified: Tuesday, 22nd August 2023 3:28:52 pm
|
||||
# Modified By: Josh.5 (jsunnex@gmail.com)
|
||||
###
|
||||
set -e
|
||||
|
||||
# Get a list of open windows
|
||||
WINDOW_IDS=$(wmctrl -l | grep -vwE "Desktop$|xfce4-panel$" | cut -f1 -d' ')
|
||||
# Close each window
|
||||
for i in ${WINDOW_IDS}; do
|
||||
wmctrl -ic "$i";
|
||||
done
|
||||
# Keep checking and waiting until all windows are closed
|
||||
while [ "X${WINDOW_IDS:-}" != "X" ]; do
|
||||
sleep 0.2;
|
||||
WINDOW_IDS=$(wmctrl -l | grep -vwE "Desktop$|xfce4-panel$" | cut -f1 -d' ')
|
||||
done
|
||||