Skip to content

Commit

Permalink
Merge pull request #130 from PierreBeucher/sunshine-desktop-config
Browse files Browse the repository at this point in the history
Sunshine desktop config
  • Loading branch information
PierreBeucher authored Feb 11, 2025
2 parents f476990 + d0097b0 commit 304d4b3
Show file tree
Hide file tree
Showing 45 changed files with 729 additions and 241 deletions.
3 changes: 2 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
docs/
**/node_modules
tmp/
**/dist
**/dist
.vagrant
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ pulumi/aws/Pulumi.*.yaml
result

# Unit test tmp dir
test/unit/core/state/TMP-v0-root-data-dir
test/unit/core/state/TMP-v0-root-data-dir
.vagrant
78 changes: 6 additions & 72 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Cloudy Pad
[![Discord](https://img.shields.io/discord/856434175455133727?style=for-the-badge&logo=discord&logoColor=ffffff&label=Chat%20with%20us&labelColor=6A7EC2&color=7389D8)](https://discord.gg/dCxDVfVnSD)
[![Discord](https://img.shields.io/discord/856434175455133727?style=for-the-badge&logo=discord&logoColor=ffffff&label=Chat%20with%20us%20on%20Discord&labelColor=6A7EC2&color=7389D8)](https://discord.gg/dCxDVfVnSD)
[![GitHub License](https://img.shields.io/github/license/PierreBeucher/cloudypad?style=for-the-badge&color=00d4c4)](./LICENSE.txt)

Cloudy Pad is a Free, Open Source alternative to GeForce Now, Blacknut and similar Cloud Gaming platforms. It lets you deploy a Cloud gaming server like [Sunshine](https://github.com/LizardByte/Sunshine) anywhere in the world and play your own games - without requiring a powerful gaming machine or a costly subscription:
Expand Down Expand Up @@ -28,12 +28,6 @@ Cloudy Pad is a Free, Open Source alternative to GeForce Now, Blacknut and simil

- [Development status 🧪](#development-status-)
- [Getting started 🚀](#getting-started-)
- [Prerequisites](#prerequisites)
- [Installation](#installation)
- [Cloud provider setup](#cloud-provider-setup)
- [Deploy your instance !](#deploy-your-instance-)
- [Play your game](#play-your-game)
- [Stop your instance after gaming sessions](#stop-your-instance-after-gaming-sessions)
- [Problem ?](#problem-)
- [Documentation](#documentation)
- [Contributing](#contributing)
Expand All @@ -47,74 +41,14 @@ This project is still at an experimental phase. While working and allowing you t

Not familiar with terms like _"Cloud gaming"_, _"Moonlight"_, _"Cloud Provider"_ _"terminal"_ or _"CLI"_ ? Visit [What's Cloud Gaming and how is Cloudy Pad useful ?](https://cloudypad.gg/what-is-cloud-gaming) first 😉

### Prerequisites

- A Cloud provider account, one of:
- AWS
- Azure
- Google Cloud
- Paperspace
- [Moonlight](https://moonlight-stream.org/) streaming client
- [Docker](https://docs.docker.com/engine/install/)
- For MacOS, [OrbStack](https://orbstack.dev/) is recommended over Docker Desktop
- Rootless Docker and non-Docker engines like Podman are not supported yet

### Installation

Install latest version of `cloudypad` CLI:

```sh
curl -fsSL https://raw.githubusercontent.com/PierreBeucher/cloudypad/master/install.sh | bash
```

For other installation methods, see [Installation](https://cloudypad.gg/usage/installation)

### Cloud provider setup

You may need to setup a few things on your Cloud provider (eg. API key or SSH key). Checkout [per-Clouder setup specifities](https://cloudypad.gg/cloud-provider-setup).

### Deploy your instance !

Once ready, create your instance with `cloudypad` CLI:

```sh
cloudypad create
# How shall we name your Cloudy Pad instance? (default: mypad)
#
# Creating Cloudy Pad instance 'mypad'
#
# [...]
#
# 🥳 Your Cloudy Pad instance is ready !
```

Cloudy Pad will:
- Prompt important information (eg. machine type, GPU, cost alerts, etc.)
- Create a new Cloud machine and related configurations automatically (you can also use an existing machine)
- Install GPU drivers and [Wolf gaming server](https://games-on-whales.github.io/wolf/stable/)
- Help your Pair with Moonlight

### Play your game

Run Moonlight and connect to your instance. Run Steam, login, install your game and enjoy.

To connect with Steam, either:
- Type your login and password directly
- Use Steam smartphone app and scan QR code (run Steam app, log in to your account and click on shield button at the bottom)

### Stop your instance after gaming sessions

Once you are done, **remember to stop your instance to avoid unnecessary costs 💸**

```sh
cloudypad stop mypad
# or
# cloudypad destroy mypad
```
[➡️ **Deploy your instance and start playing** 🎮](https://cloudypad.gg/getting-started)

### Problem ?

😱 Something went wrong? See [FAQ and known issues](https://cloudypad.gg/usage/faq.md) or [create an issue](https://github.com/PierreBeucher/cloudypad/issues)
😱 Something went wrong? A question ?

- See [FAQ and known issues](https://cloudypad.gg/usage/faq.md) or [create an issue](https://github.com/PierreBeucher/cloudypad/issues)
- Come and chat with us on [Discord](https://discord.gg/dCxDVfVnSD) !

## Documentation

Expand Down
26 changes: 26 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,32 @@ tasks:
[ $(docker run crafteo/cloudypad:local --version) = $(cat package.json | jq .version -r) ]
|| echo "Version in container image doesn't match package.json version"
#
# Local development
#

# For faster development workflow, build and import Sunshine image into dev VM
# - Build image locally as tar archive
# - Copy image to dev VM
# - Import image into dev VM
# - Run Sunshine container in dev VM
# Note: might as well use a bind mount from host to dev VM instead of scp
docker-sunshine-to-dev-vm:
cmds:
- docker buildx build containers/sunshine/ -o type=docker,dest=./tmp/cloudypad.docker.tar -t ghcr.io/pierrebeucher/cloudypad/sunshine:local
- scp -i .vagrant/machines/default/virtualbox/private_key tmp/cloudypad.docker.tar vagrant@192.168.56.43:/tmp
- ssh -i .vagrant/machines/default/virtualbox/private_key vagrant@192.168.56.43 docker load -i /tmp/cloudypad.docker.tar
- ssh -i .vagrant/machines/default/virtualbox/private_key vagrant@192.168.56.43
docker compose -f sunshine/docker-compose.yml -p sunshine up -d

build-push-image-dev:
cmds:
- docker compose -f containers/sunshine/docker-compose.yml build
- docker compose -f containers/sunshine/docker-compose.yml push

#
# Tests

# Detect potential circular deps with Madge
test-circular-deps:
cmd: npx -y madge --ts-config ./tsconfig.json -c .
Expand Down
21 changes: 21 additions & 0 deletions Vagrantfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/jammy64" # Ubuntu 22.04 LTS (Jammy)
config.vm.hostname = "cloudypad-dev"

config.vm.network "private_network", ip: "192.168.56.43"

# Sunshine access
config.vm.network "forwarded_port", guest: 47990, host: 47990

config.vm.provider "virtualbox" do |vb|
vb.memory = "4096"
vb.cpus = 4
end

config.vm.provision "shell", inline: <<-SHELL
# apt-get update
SHELL
end
11 changes: 11 additions & 0 deletions ansible/inventories/dev-vagrant.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
all:
hosts:
# Vagrant VM
"192.168.56.43":
ansible_user: vagrant
ansible_ssh_private_key_file: .vagrant/machines/default/virtualbox/private_key
ansible_ssh_common_args: '-o StrictHostKeyChecking=no'
cloudypad_web_fqdn: "192.168.56.42"
sunshine_nvidia_enable: false
sunshine_compose_pull_images: never
sunshine_image_tag: local
8 changes: 0 additions & 8 deletions ansible/inventories/test.yml

This file was deleted.

5 changes: 4 additions & 1 deletion ansible/roles/sunshine/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,7 @@ sunshine_web_password_base64: "" # Password encoded in base64, eg echo -n "<pass

# Sunshine container image to use
sunshine_image_tag: "dev"
sunshine_image_repo: "ghcr.io/pierrebeucher/cloudypad/sunshine"
sunshine_image_repo: "ghcr.io/pierrebeucher/cloudypad/sunshine"

# Whether to force pull images when deploying Docker Compose Sunshine containers
sunshine_compose_pull_images: always
2 changes: 1 addition & 1 deletion ansible/roles/sunshine/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@
build: always
state: present
files: "{{ sunshine_compose_files }}"
pull: always
pull: "{{ sunshine_compose_pull_images }}"
35 changes: 25 additions & 10 deletions containers/sunshine/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,6 @@ RUN --mount=type=cache,target=/var/cache --mount=type=tmpfs,target=/var/log \
pulseaudio \
gettext-base

#
# Desktop
#
RUN --mount=type=cache,target=/var/cache --mount=type=tmpfs,target=/var/log \
apt install -y xfce4

#
# Sunshine
#
Expand Down Expand Up @@ -127,6 +121,23 @@ RUN --mount=type=cache,target=/var/cache --mount=type=tmpfs,target=/var/log \
apt install -y ./steam.deb && \
rm steam.deb

#
# Desktop
#
# Install xfce4 desktop environment
# but remove xfce4-panel to void showinf uneeded/unwanted panels (see https://unix.stackexchange.com/questions/38048/how-to-remove-all-the-panels-in-xfce)
#
RUN --mount=type=cache,target=/var/cache --mount=type=tmpfs,target=/var/log \
apt install -y xfce4 && \
apt remove -y xfce4-panel && \
apt clean

# Install sudo
RUN --mount=type=cache,target=/var/cache --mount=type=tmpfs,target=/var/log \
apt update && \
apt install -y sudo && \
apt clean

# # TODO Local (for debug)
# # Keep here ?
RUN --mount=type=cache,target=/var/cache --mount=type=tmpfs,target=/var/log \
Expand All @@ -146,6 +157,9 @@ ENV CLOUDYPAD_USER=cloudy
ENV CLOUDYPAD_DATA_DIR=/cloudy/data
ENV CLOUDYPAD_LOG_DIR=/cloudy/log
ENV CLOUDYPAD_CONF_DIR=/cloudy/conf
# TODO as tmpfs ?
ENV CLOUDYPAD_RUNTIME_DIR=/cloudy/runtime
ENV CLOUDYPAD_BIN_DIR=/cloudy/bin

# Default name for Sunshine server (as shown by Moonlight)
# Used in sunshine.conf templates
Expand All @@ -157,12 +171,10 @@ ENV SUNSHINE_SERVER_NAME="Sunshine"
# Setting proper XDG_* variables allow more control other config and data persistence
# See https://specifications.freedesktop.org/basedir-spec/latest/
#
ENV XDG_RUNTIME_DIR=/cloudy/runtime
ENV XDG_RUNTIME_DIR=$CLOUDYPAD_RUNTIME_DIR
ENV XDG_CONFIG_HOME=$CLOUDYPAD_CONF_DIR
ENV XDG_CACHE_HOME=/home/$CLOUDYPAD_USER/.cache

# TODO persist this folder ?
ENV XDG_CONFIG_HOME=/home/$CLOUDYPAD_USER/.config

# Write data in known directory for persistence
# XDG_DATA_HOME is used by various programs (like Steam) to store data
# Use this known directory to easily persist it as bind mount or volume
Expand All @@ -180,6 +192,9 @@ RUN useradd -m -d /home/cloudy -s /bin/bash -u 1001 $CLOUDYPAD_USER

COPY overlay /

# Allow user "cloudy" to stop container
RUN echo "cloudy ALL=(ALL) NOPASSWD: ${CLOUDYPAD_BIN_DIR}/stop-supervisord.sh" > /etc/sudoers.d/cloudy-stop-container

# Contain various Cloudy Pad scripts, add to PATH for easier use
ENV PATH=$PATH:/cloudy/bin

Expand Down
3 changes: 2 additions & 1 deletion containers/sunshine/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Build and debug compose file, not usable to run container
# Development compose file to build and debug Sunshine container
# Not suiable to run container
# See ansible/roles/sunshine/templates/docker-compose*.yml for example usage with Compose
services:
cloudy:
Expand Down
2 changes: 1 addition & 1 deletion containers/sunshine/overlay/cloudy/bin/setup-dirs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ chown $CLOUDYPAD_USER:$CLOUDYPAD_USER \
$XDG_CONFIG_HOME \
$XDG_DATA_HOME

chmod 0770 \
chmod 0700 \
$CLOUDYPAD_DATA_DIR \
$CLOUDYPAD_LOG_DIR \
$XDG_RUNTIME_DIR \
Expand Down
14 changes: 14 additions & 0 deletions containers/sunshine/overlay/cloudy/bin/start-desktop.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,19 @@

wait-x-availability.sh

# Copy desktop entry to user's desktop and ensure they are executable
mkdir -p $HOME/Desktop/
cp $XDG_CONFIG_HOME/desktop-apps/* $HOME/Desktop/

for f in $HOME/Desktop/*.desktop; do
chmod +x "$f"

# Must be trusted to be run by user
# See https://stackoverflow.com/questions/51747456/is-it-possible-to-modify-gnome-desktop-file-metadata-from-non-gui-session-using
# and https://forum.xfce.org/viewtopic.php?pid=70661#p70661
dbus-launch gio set -t string "$f" "metadata::trusted" yes
dbus-launch gio set -t string "$f" "metadata::xfce-exe-checksum" "$(sha256sum $f | awk '{print $1}')"
done

# Shows a bunch of warning but at least doesn't crash ¯\_(ツ)_/¯
startxfce4
3 changes: 3 additions & 0 deletions containers/sunshine/overlay/cloudy/bin/start-steam.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
#!/usr/bin/env bash

wait-x-availability.sh

steam
9 changes: 9 additions & 0 deletions containers/sunshine/overlay/cloudy/bin/stop-container-user.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash

# Can be used by user to stop session

gnome-terminal -- bash -c "echo 'Shutting down... Your session will end in a few seconds.'; \
echo 'You can also press CTRL+ALT+SHIFT+Q to exit session.'; \
sleep 999"

sudo /cloudy/bin/stop-supervisord.sh
12 changes: 12 additions & 0 deletions containers/sunshine/overlay/cloudy/bin/stop-supervisord.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env bash

# Force stop container by killing its own PID 1.
# PID 1 should be supervisord which will stop all services gracefully and shutdown
# effectively stopping the container.
#
# This script it aimed to provide an "easy' way to stop Sunshine session since
# typing "CTRL+ALT+SHIFT+Q" is not easy for some user, allowing to have a shortcut on desktop pointing to this script.
# Container will probably restart instantly but that's expected

# send SIGTERM to supervisord for graceful shutdown
kill -SIGTERM 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Desktop entry taken from /usr/share/applications/steam.desktop
[Desktop Entry]
Name=Exit session
Exec=$CLOUDYPAD_BIN_DIR/stop-container-user.sh
Icon=system-shutdown
Terminal=true
Type=Application
Categories=Network;FileTransfer;Game;
12 changes: 12 additions & 0 deletions containers/sunshine/overlay/cloudy/conf/desktop-apps/steam.desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Desktop entry taken from /usr/share/applications/steam.desktop
[Desktop Entry]
Name=Steam
Exec=/usr/bin/steam %U
Icon=steam
Terminal=true
Type=Application
Categories=Network;FileTransfer;Game;
MimeType=x-scheme-handler/steam;x-scheme-handler/steamlink;
Actions=Store;Community;Library;Servers;Screenshots;News;Settings;BigPicture;Friends;
PrefersNonDefaultGPU=true
X-KDE-RunOnDiscreteGpu=true
11 changes: 11 additions & 0 deletions containers/sunshine/overlay/cloudy/conf/sunshine/apps.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"env": {
"PATH": "$(PATH):$(HOME)/.local/bin"
},
"apps": [
{
"name": "Steam",
"image-path": "steam.png"
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ origin_web_ui_allowed = lan
min_log_level = info

# Keep state files in Cloudy Pad data dir to persist on container recreation
# They are by default saved in XDG_CONFIG_HOME but this folder is not persisted voluntarily
credentials_file = /cloudy/data/sunshine/sunshine_credentials.json
file_state = /cloudy/data/sunshine/sunshine_state.json
pkey = /cloudy/data/sunshine/pkey.pem
Expand Down
Loading

0 comments on commit 304d4b3

Please sign in to comment.