diff --git a/Dockerfile b/Dockerfile index 4718804..fc3bec3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,8 +7,16 @@ RUN apt-get update && apt-get install -y \ xfce4 \ xfce4-goodies \ sudo \ + pulseaudio \ + gstreamer1.0-tools gstreamer1.0-plugins-good \ + gstreamer1.0-plugins-bad \ + gstreamer1.0-plugins-ugly \ + tigervnc-standalone-server tigervnc-common \ + alsa dbus \ + nano vim \ && apt-get clean + RUN mkdir /var/run/sshd RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config @@ -27,5 +35,7 @@ RUN echo "export VISIBLE=now" >> /etc/profile COPY create_ubuntu_user.sh /usr/local/bin/create_ubuntu_user.sh RUN chmod +x /usr/local/bin/create_ubuntu_user.sh +COPY start_services.sh /usr/local/bin/start_services.sh + EXPOSE 22 5901 CMD ["/usr/sbin/sshd", "-D"] diff --git a/README.md b/README.md index e69de29..12b5fc1 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,28 @@ +PRE-REQUISTE: +./setup.sh + +This will basically run: +docker network create frontend +docker network create backend + +Create and bring up an Ubuntu instance with the following: +./create_user.sh john_doe 1001 2201 5901 your_secure_password +./connect_and_stream.sh + +The ~ (home) directory is saved on the local disk in the ./data directory. + +If you need to bring up a specific user: +docker-compose -f docker-compose.user_1001.yml build +docker-compose -f docker-compose.user_1001.yml up -d + +OR MANUALLY: + +Locally, type: +pulseaudio --load=module-native-protocol-tcp --exit-idle-time=-1 --daemon + +export DISPLAY=:0 +ssh -Y -C -p 2201 -L 4713:localhost:4713 -L 5000:localhost:5000 john_doe@localhost + +On the remote container: +paplay /usr/share/sounds/alsa/Front_Center.wav +PULSE_SERVER=unix:/tmp/pulseaudio.socket firefox \ No newline at end of file diff --git a/connect_and_stream.sh b/connect_and_stream.sh new file mode 100755 index 0000000..ffc53bd --- /dev/null +++ b/connect_and_stream.sh @@ -0,0 +1,55 @@ +#!/bin/bash + +# connect_and_stream.sh + +SERVER_IP="localhost" +SSH_PORT="2201" # or whatever SSH port you're using +USERNAME="john_doe" # or the appropriate username +REMOTE_AUDIO_PORT="5000" +LOCAL_AUDIO_PORT="5000" +PULSE_PORT="4713" + +# Function to find an available port +find_available_port() { + local port=$1 + while ! nc -z localhost $port &>/dev/null; do + ((port++)) + done + echo $port +} + +# Function to clean up background processes on script exit +cleanup() { + echo "Cleaning up..." + if [ ! -z "$SSH_PID" ]; then + kill $SSH_PID + fi + exit +} + +# Set up the cleanup function to run on script exit +trap cleanup EXIT + +# Find available ports +LOCAL_AUDIO_PORT=$(find_available_port $LOCAL_AUDIO_PORT) +PULSE_PORT=$(find_available_port $PULSE_PORT) + +echo "Using local audio port: $LOCAL_AUDIO_PORT" +echo "Using PulseAudio port: $PULSE_PORT" + +# Start SSH tunnel in the background +ssh -f -N -L ${LOCAL_AUDIO_PORT}:localhost:${REMOTE_AUDIO_PORT} -L ${PULSE_PORT}:localhost:4713 -p ${SSH_PORT} ${USERNAME}@${SERVER_IP} +SSH_PID=$! + +# Wait a moment for the tunnel to establish +sleep 2 + +# Set PULSE_SERVER to use the forwarded port +export PULSE_SERVER=tcp:localhost:${PULSE_PORT} + +# Start GStreamer client +#gst-launch-1.0 udpsrc uri=udp://localhost:${LOCAL_AUDIO_PORT} caps="application/x-rtp,media=audio,clock-rate=48000,encoding-name=OPUS" ! rtpopusdepay ! opusdec ! audioconvert ! autoaudiosink +gst-launch-1.0 udpsrc port=${LOCAL_AUDIO_PORT} caps="application/x-rtp,media=audio,clock-rate=48000,encoding-name=OPUS" ! rtpopusdepay ! opusdec ! audioconvert ! autoaudiosink + +# The script will keep running until you stop it (Ctrl+C) +# When stopped, the cleanup function will kill the SSH tunnel \ No newline at end of file diff --git a/create_ubuntu_user.sh b/create_ubuntu_user.sh index 0e65129..0e82e56 100755 --- a/create_ubuntu_user.sh +++ b/create_ubuntu_user.sh @@ -18,4 +18,19 @@ su - $USERNAME -c "mkdir -p ~/.vnc && x11vnc -storepasswd $PASSWORD ~/.vnc/passw # Set up X11 forwarding for the user echo "export DISPLAY=host.docker.internal:0" >> /home/$USERNAME/.bashrc -echo "User $USERNAME created with the provided password." +# Set up PulseAudio +su - $USERNAME -c "mkdir -p ~/.config/pulse" +su - $USERNAME -c "echo 'autospawn = yes' > ~/.config/pulse/client.conf" +su - $USERNAME -c "echo 'daemon-binary = /usr/bin/pulseaudio' >> ~/.config/pulse/client.conf" +su - $USERNAME -c "echo 'enable-shm = false' >> ~/.config/pulse/client.conf" +su - $USERNAME -c "echo 'enable-memfd = yes' >> ~/.config/pulse/client.conf" + +su - $USERNAME -c "echo 'load-module module-native-protocol-unix' > ~/.config/pulse/default.pa" +su - $USERNAME -c "echo 'load-module module-native-protocol-tcp auth-anonymous=1' >> ~/.config/pulse/default.pa" +su - $USERNAME -c "echo 'load-module module-always-sink' >> ~/.config/pulse/default.pa" +# su - $USERNAME -c "echo 'load-module module-null-sink' >> ~/.config/pulse/default.pa" +# su - $USERNAME -c "echo 'load-module module-pipe-sink' >> ~/.config/pulse/default.pa" +su - $USERNAME -c "echo 'load-module module-virtual-sink sink_name=virtual_output' >> ~/.config/pulse/default.pa" +su - $USERNAME -c "echo 'set-default-sink virtual_output' >> ~/.config/pulse/default.pa" + +echo "User $USERNAME created with the provided password and PulseAudio configured." \ No newline at end of file diff --git a/create_user.sh b/create_user.sh index 44ef083..e8ffdd6 100755 --- a/create_user.sh +++ b/create_user.sh @@ -33,7 +33,7 @@ services: - SYS_ADMIN security_opt: - seccomp:unconfined - command: ["/bin/bash", "-c", "/usr/local/bin/create_ubuntu_user.sh ${USER_NAME} ${PASSWORD} && /usr/sbin/sshd -D"] + command: ["/bin/bash", "-c", "/usr/local/bin/create_ubuntu_user.sh ${USER_NAME} ${PASSWORD} && /usr/local/bin/start_services.sh"] networks: frontend: diff --git a/setup.sh b/setup.sh new file mode 100755 index 0000000..8b0a061 --- /dev/null +++ b/setup.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# setup.sh + +# Build the base image +docker build -t ubuntu_dev_env . + +# Create networks +docker network create frontend +docker network create backend + diff --git a/start.sh b/start.sh deleted file mode 100755 index 5ec791c..0000000 --- a/start.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -# Start SSH -/usr/sbin/sshd - -# Start Xvfb -Xvfb :1 -screen 0 1024x768x16 & - -# Start VNC server -vncserver :1 -geometry 1024x768 -depth 16 -SecurityTypes None - -# Keep the container running -tail -f /dev/null diff --git a/start_services.sh b/start_services.sh new file mode 100755 index 0000000..767f6c6 --- /dev/null +++ b/start_services.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +# Start D-Bus +mkdir -p /var/run/dbus +dbus-daemon --system --fork + +# Start SSH +/usr/sbin/sshd + +# Start Xvfb +Xvfb :1 -screen 0 1024x768x16 & + +# Start VNC server +vncserver :1 -geometry 1024x768 -depth 16 -SecurityTypes None + +# Start PulseAudio +su - $USER_NAME -c "pulseaudio --start -D --verbose" + +# Set up virtual audio output +su - $USER_NAME -c "pactl unload-module module-null-sink || true" +su - $USER_NAME -c "pactl unload-module module-pipe-sink || true" +su - $USER_NAME -c "pactl load-module module-virtual-sink sink_name=virtual_output" +su - $USER_NAME -c "pactl set-default-sink virtual_output" + +# Ensure all audio streams are moved to the virtual_output +su - $USER_NAME -c "pactl list short sink-inputs | cut -f1 | while read stream; do pactl move-sink-input \$stream virtual_output; done" + +# Start audio streaming +su - $USER_NAME -c "gst-launch-1.0 pulsesrc device=virtual_output.monitor ! audioconvert ! opusenc ! rtpopuspay ! udpsink host=host.docker.internal port=5000 &" + +# Keep the container running +tail -f /dev/null \ No newline at end of file