Skip to content

Commit 7bbc6bc

Browse files
Merge pull request #352 from PierreBeucher/minor-tweaks
Minor tweaks
2 parents 2f60eea + 7e18881 commit 7bbc6bc

7 files changed

Lines changed: 126 additions & 16 deletions

File tree

containers/sunshine/Dockerfile

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,29 @@ WORKDIR /app
55
# Sunshine
66
# https://github.com/LizardByte/Sunshine/releases
77
FROM download-base AS download-sunshine
8-
ARG SUNSHINE_VERSION=2026.218.44016
9-
RUN curl -L -o /app/sunshine.deb "https://github.com/LizardByte/Sunshine/releases/download/v${SUNSHINE_VERSION}/sunshine-ubuntu-24.04-amd64.deb"
8+
ARG SUNSHINE_VERSION=2025.924.154138
9+
RUN curl -fL -o /app/sunshine.deb "https://github.com/LizardByte/Sunshine/releases/download/v${SUNSHINE_VERSION}/sunshine-ubuntu-24.04-amd64.deb"
1010

1111
# Steam
1212
# https://repo.steampowered.com/steam/archive/stable/
1313
FROM download-base AS download-steam
1414
ARG STEAM_VERSION="1.0.0.81"
15-
RUN curl -o /app/steam-libs-amd64.deb "https://repo.steampowered.com/steam/archive/stable/steam-libs-amd64_${STEAM_VERSION}_amd64.deb"
16-
RUN curl -o /app/steam-libs-i386.deb "https://repo.steampowered.com/steam/archive/stable/steam-libs-i386_${STEAM_VERSION}_i386.deb"
17-
RUN curl -o /app/steam.deb "https://repo.steampowered.com/steam/archive/stable/steam-launcher_${STEAM_VERSION}_all.deb"
15+
RUN curl -f -o /app/steam-libs-amd64.deb "https://repo.steampowered.com/steam/archive/stable/steam-libs-amd64_${STEAM_VERSION}_amd64.deb"
16+
RUN curl -f -o /app/steam-libs-i386.deb "https://repo.steampowered.com/steam/archive/stable/steam-libs-i386_${STEAM_VERSION}_i386.deb"
17+
RUN curl -f -o /app/steam.deb "https://repo.steampowered.com/steam/archive/stable/steam-launcher_${STEAM_VERSION}_all.deb"
1818

1919
# Lutris
2020
# https://github.com/lutris/lutris/releases
2121
FROM download-base AS download-lutris
2222
ARG LUTRIS_VERSION="0.5.20"
23-
RUN curl -L -o /app/lutris.deb "https://github.com/lutris/lutris/releases/download/v${LUTRIS_VERSION}/lutris_${LUTRIS_VERSION}_all.deb"
23+
RUN curl -fL -o /app/lutris.deb "https://github.com/lutris/lutris/releases/download/v${LUTRIS_VERSION}/lutris_${LUTRIS_VERSION}_all.deb"
2424

2525
# Heroic
2626
# https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher/releases
2727
FROM download-base AS download-heroic
2828
ARG HEROIC_VERSION="2.19.1"
29-
RUN curl -L -o /app/heroic.deb "https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher/releases/download/v${HEROIC_VERSION}/Heroic-${HEROIC_VERSION}-linux-amd64.deb"
29+
30+
RUN curl -fL -o /app/heroic.deb "https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher/releases/download/v${HEROIC_VERSION}/Heroic-${HEROIC_VERSION}-linux-amd64.deb"
3031

3132
#
3233
# Sunshine image based on Ubuntu 24.04
@@ -178,7 +179,6 @@ RUN locale-gen en_US.UTF-8 && \
178179
RUN --mount=type=cache,target=/var/cache --mount=type=tmpfs,target=/var/log --mount=type=bind,from=download-sunshine,source=/app,target=/app <<_SUNSHINE
179180

180181
set -e
181-
182182
apt update
183183
apt install -y /app/sunshine.deb
184184

containers/sunshine/overlay/cloudy/conf/xfce4-default/panel/launcher-12/lutris.desktop

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[Desktop Entry]
2-
Name=Leroic
2+
Name=Lutris
33
Comment=Managing and play games on Lutris
44
Exec=lutris-start.sh
55
Icon=lutris

docs/src/contributing/contribution-guide.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ Here's a typical workflow outline for contributions:
3737
- [Ansible playbook](#ansible-playbook)
3838
- [Local Pulumi stack manipulation](#local-pulumi-stack-manipulation)
3939
- [Local Virtual Machine as Cloudy Pad instance](#local-virtual-machine-as-cloudy-pad-instance)
40+
- [Connect to Cloudy Pad VM and container](#connect-to-cloudy-pad-vm-and-container)
41+
- [Debug Proton / Wine and game run](#debug-proton--wine-and-game-run)
42+
- [Debug process CPU usage or affinity](#debug-process-cpu-usage-or-affinity)
43+
- [Debug process environment variable](#debug-process-environment-variable)
44+
- [Enable debug log with Steam and Proton](#enable-debug-log-with-steam-and-proton)
4045
- [Create a Pull Request with your changes](#create-a-pull-request-with-your-changes)
4146
- [Review process](#review-process)
4247
- [Useful commands](#useful-commands)
@@ -349,6 +354,78 @@ vagrant ssh
349354
$ docker compose -f /vagrant/test/resources/docker-compose.vagrant.yml -p sunshine up -d --force-recreate
350355
```
351356

357+
### Connect to Cloudy Pad VM and container
358+
359+
To connect via SSH on instance, see: [Connect via SSH](../usage/ssh.md)
360+
361+
### Debug Proton / Wine and game run
362+
363+
To run directly Proton or Wine and see how it behaves, first run the game in a standard way and re-use the same command to reproduce issue or situation.
364+
365+
Identify process running game, then get their env variables:
366+
367+
```sh
368+
ps -ef
369+
370+
GAME_PID=1234 cat proc/$GAME_PID$/environ | tr '\0' '\n'
371+
```
372+
373+
Steam specifics: variables we want to re-use:
374+
375+
```sh
376+
export STEAM_COMPAT_CLIENT_INSTALL_PATH="/cloudy/data/Steam"
377+
export STEAM_COMPAT_DATA_PATH="/cloudy/data/Steam/steamapps/compatdata/1903340"
378+
```
379+
380+
Then run game manually (re-use actual command), eg.:
381+
382+
```sh
383+
python3 "/cloudy/data/Steam/steamapps/common/Proton 10.0/proton" waitforexitandrun "C:\\windows\\system32\\cmd.exe" /c "path/to/game.exe"
384+
```
385+
386+
Example for Steam with Expedition 33:
387+
388+
```sh
389+
python3 /cloudy/data/Steam/steamapps/common/Proton 10.0/proton waitforexitandrun /cloudy/data/Steam/steamapps/common/Expedition 33/Expedition33_Steam.exe
390+
```
391+
392+
### Debug process CPU usage or affinity
393+
394+
Specific instructions to debug CPU usage, especially linked to CPU affinity. (eg. for [#335](https://github.com/PierreBeucher/cloudypad/issues/335))
395+
396+
```sh
397+
# Show all process
398+
ps -ef
399+
400+
# Show process using NVIDIA GPU
401+
nvidia-smi
402+
403+
# Show process CPU affinity
404+
taskset -pc PID
405+
```
406+
407+
### Debug process environment variable
408+
409+
```sh
410+
cat /proc/5096/environ | tr '\0' '\n'
411+
```
412+
413+
### Enable debug log with Steam and Proton
414+
415+
Connect on instance and `docker exec -it -u cloudy cloudy bash` to run a shell in container as cloudy user, then run Steam directly:
416+
417+
```sh
418+
STEAM_LINUX_RUNTIME_LOG=1 STEAM_LINUX_RUNTIME_VERBOSE=1 PRESSURE_VESSEL_VERBOSE=1 PROTON_LOG=1 PROTON_LOG_DIR=/tmp steam
419+
```
420+
421+
Possibly also add (as per [Steam debug logging instructions](https://github.com/ValveSoftware/steam-runtime/blob/master/doc/reporting-steamlinuxruntime-bugs.md) ):
422+
423+
```sh
424+
CAPSULE_DEBUG=all
425+
G_MESSAGES_DEBUG=all
426+
```
427+
428+
352429
## Create a Pull Request with your changes
353430

354431
When your changes are ready, you can [create a Pull Request](https://github.com/PierreBeucher/cloudypad/pulls). Please make sure to:

docs/src/contributing/maintenance.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ Then:
7373
- [ ] Base image version `FROM` - See available tags from [Docker Hub](https://hub.docker.com/_/ubuntu). Make sure to use the imaghe SHA for reproducibility.
7474
- [ ] Steam version `CLOUDYPAD_STEAM_VERSION` - see stable version at [Steam archive](https://repo.steampowered.com/steam/archive/stable)
7575
- [ ] Update `SUNSHINE_VERSION` with [latest Sunshine release](https://github.com/LizardByte/Sunshine/releases)
76+
- Prefer the Latest release
77+
- Do NOT use Release Candidate or Pre-release, make sure to use actual release. Pre-release and RC may be removed from GitHub later, we need a release that will be kept available to ensure reproducibility of our build.
7678
- [ ] Update `LUTRIS_VERSION` with [latest Lutris release](https://github.com/lutris/lutris/releases)
7779
- [ ] Update `HEROIC_VERSION` with [latest Heroic Games Launcher version](https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher/releases)
7880
- [ ] Update `CLOUDYPAD_HEROIC_DEFAULT_GEPROTON_VERSION` with [latest GE-Proton version](https://github.com/GloriousEggroll/proton-ge-custom/releases)

src/cli/command.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ export const CLI_OPTION_AUTO_STOP_TIMEOUT = new Option('--autostop-timeout <seco
125125

126126
export const CLI_OPTION_ANSIBLE_ADDITIONAL_ARGS = new Option('--ansible-additional-args <args>', 'Additional Ansible arguments to pass to configuration, eg. "--tags data-disk -vvv"')
127127

128+
export const CLI_OPTION_ANSIBLE_ARGS_OVERRIDE = new Option('--ansible-args-override <args>', 'Override Ansible arguments to pass to configuration, eg. "--tags data-disk -vvv"')
129+
128130
export const CLI_OPTION_RETRIES = new Option('--retries <number>', 'Number of retries when deploying, configuring, starting, stopping or destroying instance')
129131
.argParser(parseInt)
130132
export const CLI_OPTION_RETRY_DELAY = new Option('--retry-delay <seconds>', 'Retry delay in seconds when deploying, configuring, starting, stopping or destroying instance')

src/cli/program.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { CloudypadClient } from '../core/client';
1717
import { CoreConfig } from '../core/config/interface';
1818
import { InstanceManagerBuilder } from '../core/manager-builder';
1919
import { InstanceManager } from '../core/manager';
20-
import { CLI_OPTION_RETRIES, CLI_OPTION_RETRY_DELAY, CLI_OPTION_FORCE_PULUMI_CANCEL } from './command';
20+
import { CLI_OPTION_RETRIES, CLI_OPTION_RETRY_DELAY, CLI_OPTION_FORCE_PULUMI_CANCEL, CLI_OPTION_ANSIBLE_ADDITIONAL_ARGS, CLI_OPTION_ANSIBLE_ARGS_OVERRIDE } from './command';
2121

2222
const logger = getLogger("program")
2323

@@ -184,7 +184,8 @@ export function buildProgram(){
184184
analyticsClient.sendEvent(RUN_COMMAND_STOP)
185185

186186
console.info(`Stopping instance ${name}...`)
187-
console.info(`ℹ️ Stopping may take some time to complete while your instance's data is put to sleep for better cost efficiency (data disk snapshot may be long).`)
187+
// need 2 spaces otherwise might not show properly
188+
console.info(`ℹ️ Stopping may take some time to complete while your instance's data is put to sleep for better cost efficiency (data disk snapshot may be long).`)
188189

189190
const m = await getInstanceManager(name)
190191
await m.stop({
@@ -293,6 +294,7 @@ export function buildProgram(){
293294
.addOption(CLI_OPTION_RETRIES)
294295
.addOption(CLI_OPTION_RETRY_DELAY)
295296
.addOption(CLI_OPTION_FORCE_PULUMI_CANCEL)
297+
.addOption(CLI_OPTION_ANSIBLE_ARGS_OVERRIDE)
296298
.action(async (name, opts) => {
297299
try {
298300
analyticsClient.sendEvent(RUN_COMMAND_CONFIGURE)
@@ -301,7 +303,8 @@ export function buildProgram(){
301303
await m.configure({
302304
retries: opts.retries,
303305
retryDelaySeconds: opts.retryDelay,
304-
pulumiCancel: opts.forcePulumiCancel
306+
pulumiCancel: opts.forcePulumiCancel,
307+
ansibleArgsOverride: opts.ansibleArgsOverride ? [opts.ansibleArgsOverride] : undefined
305308
})
306309

307310
console.info("")
@@ -318,6 +321,7 @@ export function buildProgram(){
318321
.addOption(CLI_OPTION_RETRIES)
319322
.addOption(CLI_OPTION_RETRY_DELAY)
320323
.addOption(CLI_OPTION_FORCE_PULUMI_CANCEL)
324+
.addOption(CLI_OPTION_ANSIBLE_ARGS_OVERRIDE)
321325
.action(async (name, opts) => {
322326

323327
const manager = await getInstanceManager(name)
@@ -334,7 +338,8 @@ export function buildProgram(){
334338
await manager.deploy({
335339
retries: opts.retries,
336340
retryDelaySeconds: opts.retryDelay,
337-
pulumiCancel: opts.forcePulumiCancel
341+
pulumiCancel: opts.forcePulumiCancel,
342+
ansibleArgsOverride: opts.ansibleArgsOverride ? [opts.ansibleArgsOverride] : undefined
338343
})
339344
})
340345

src/core/manager.ts

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,17 @@ export interface ActionOptions {
3535
}
3636

3737
export interface DeployOptions extends ActionOptions {
38+
/**
39+
* Override Ansible arguments to pass to configuration, e.g. ["--tags", "nvidia-container-toolkit"]
40+
*/
41+
ansibleArgsOverride?: string[]
3842
}
3943

4044
export interface ConfigureOptions extends ActionOptions {
45+
/**
46+
* Override Ansible arguments to pass to configuration, e.g. ["--tags", "nvidia-container-toolkit"]
47+
*/
48+
ansibleArgsOverride?: string[]
4149
}
4250

4351
export interface ProvisionOptions extends ActionOptions {
@@ -266,9 +274,15 @@ export class GenericInstanceManager<ST extends InstanceStateV1> implements Insta
266274

267275
this.logger.debug(`Configuring instance ${this.name()}`)
268276

269-
const currentState = await this.getState()
270-
const configurationAnsibleAdditionalArgs = currentState.configuration.input.ansible?.additionalArgs ?
271-
[currentState.configuration.input.ansible.additionalArgs] : undefined
277+
// Prefer CLI-provided args override over state-stored args
278+
let configurationAnsibleAdditionalArgs: string[] | undefined
279+
if (opts?.ansibleArgsOverride) {
280+
configurationAnsibleAdditionalArgs = opts.ansibleArgsOverride
281+
} else {
282+
const currentState = await this.getState()
283+
configurationAnsibleAdditionalArgs = currentState.configuration.input.ansible?.additionalArgs ?
284+
[currentState.configuration.input.ansible.additionalArgs] : undefined
285+
}
272286

273287
await this.addEvent(InstanceEventEnum.ConfigurationBegin)
274288

@@ -352,6 +366,16 @@ export class GenericInstanceManager<ST extends InstanceStateV1> implements Insta
352366

353367
await this.doProvision(opts)
354368

369+
// Check if server is actually running after provision
370+
// Provisioning may not have started the server if it was existing but not running
371+
// eg. if instance server was stopped by auto-stop feature rather than stop() operation
372+
const runner = await this.buildRunner()
373+
const serverStatus = await runner.serverStatus()
374+
if(serverStatus !== ServerRunningStatus.Running){
375+
this.logger.debug(`Server is not running after provision (status: ${serverStatus}), starting it now`)
376+
await runner.start({ wait: true })
377+
}
378+
355379
// always reconfigured instance using limited Ansible run to avoid re-running full configuration on every start
356380
await this.doConfigure(['-t', 'ratelimit,data-disk,sunshine'])
357381
}

0 commit comments

Comments
 (0)