iaincollins / icarus

ICARUS Terminal for Elite Dangerous
ISC License
182 stars 11 forks source link

Dockerized Icarus-terminal suggestion #56

Open goffy59 opened 2 months ago

goffy59 commented 2 months ago

Hey team,

First off, I just want to say I absolutely love what you've built here—this project is seriously awesome! I'm not super deep into coding or the technical side of things, so I don't have the chops to contribute directly to the tracker. But I did want to share something I put together that I think might help others in the community.

I dockerized the Icarus-terminal to run on a server at home. The only thing not inside the Docker container is a systemd unit to mount a folder via SSHFS to read the journal, and then it checks it in case your gaming rig sleeps. I host this on one of my homelab Docker VM servers. I use fedora silverblue as my daily driver/gaming rig. My hypervisor runs a vm server that uses uses ubuntu server to run dockers. I apologize if I cant provide more detail to make it work but for the project leader and or those who know here you go. Yes chatgpt helped me acheive this and yes it seems to work great and all i do is then open a web page on one of my monitors on the gaming rig or any screen or computer or tv. its sweet!

Docker Run Command

docker run -d --name icarus-terminal --cap-add SYS_ADMIN \
  -v /mnt/elite-dangerous:/usr/src/app/logs \
  -e LOG_DIR=/usr/src/app/logs \
  -p 3300:3300 \
  --restart always \
  icarus-terminal

SSHFS Mount Script

#!/bin/bash

# Configuration
LOGFILE="/var/log/sshfs-mount.log"
MOUNT_POINT="/mnt/elite-dangerous"
REMOTE_DIR="/var/home/goffy59/.var/app/com.valvesoftware.Steam/.local/share/Steam/steamapps/compatdata/359320/pfx/drive_c/users/steamuser/Saved Games/Frontier Developments/Elite Dangerous/"
REMOTE_USER="goffy59"
REMOTE_HOST="pg1"
RETRY_DELAY=60
RESTART_DELAY=10

# Log function
log() {
    echo "$(date): $1" >> "$LOGFILE"
}

# Check if remote server is reachable
check_remote_server() {
    log "Checking if remote server $REMOTE_HOST is reachable..."
    if ssh -o ConnectTimeout=10 "$REMOTE_USER@$REMOTE_HOST" 'exit' 2>/dev/null; then
        return 0
    else
        return 1
    fi
}

# Check if mount point is mounted
check_mount() {
    if mountpoint -q "$MOUNT_POINT"; then
        return 0
    else
        return 1
    fi
}

# Mount remote directory
mount_remote_directory() {
    log "Mounting remote directory $REMOTE_DIR to $MOUNT_POINT..."
    if sshfs -o allow_other,uid=1000,gid=1000 -o cache=yes -o max_read=16384 "$REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR" "$MOUNT_POINT"; then
        log "Mount successful."
        return 0
    else
        log "Mount failed."
        return 1
    fi
}

# Restart Docker container
restart_docker_container() {
    log "Restarting Docker container icarus-terminal..."
    docker restart icarus-terminal
    sleep "$RESTART_DELAY"
    # Removed rdesktop container restart
}

# Main function
main() {
    while true; do
        if check_remote_server; then
            if ! check_mount; then
                # Mount the remote directory if not already mounted
                if mount_remote_directory; then
                    # Restart Docker container if mount is successful
                    restart_docker_container
                fi
            fi
        else
            log "Remote server $REMOTE_HOST is not reachable. Retrying in $RETRY_DELAY seconds..."
        fi
        sleep "$RETRY_DELAY"
    done
}

# Run the main function
main

Systemd Unit to Run Script

[Unit]
Description=SSHFS Mount Service
After=network-online.target
Wants=network-online.target

[Service]
ExecStart=/usr/local/bin/sshfs-mount.sh
Restart=always
User=root
Group=root
StandardOutput=append:/var/log/sshfs-mount.log
StandardError=append:/var/log/sshfs-mount.log

[Install]
WantedBy=multi-user.target

Dockerfile

# Use an official Node.js image as a base
FROM node:18

# Set the working directory inside the container
WORKDIR /usr/src/app

# Install SSHFS, FUSE3, and Supervisor
RUN apt-get update && \
    apt-get install -y fuse3 sshfs supervisor && \
    apt-get clean

# Enable allow_other in FUSE configuration
RUN echo "user_allow_other" >> /etc/fuse.conf

# Clone the ICARUS Terminal repository into the current directory
RUN git clone https://github.com/iaincollins/icarus.git ./

# Install Node.js dependencies
RUN npm install

# Expose the port ICARUS Terminal will run on
EXPOSE 3300

# Set environment variables (adjust LOG_DIR later)
ENV LOG_DIR=/logs

# Ensure logs directory exists
RUN mkdir -p /usr/src/app/logs && \
    chmod -R 777 /usr/src/app/logs

# Copy the Supervisor configuration
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf

# Copy the startup script
COPY start-app.sh /usr/src/app/start-app.sh
RUN chmod +x /usr/src/app/start-app.sh

# Command to start Supervisor, which will manage the app
CMD ["supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]

.env File

LOG_DIR=/mnt/elite-dangerous

start-app.sh Script

#!/bin/bash

# Function to check the logs for specific error messages
check_logs() {
    log_file=/usr/src/app/logs/icarus.log

    if grep -q "Failed to lookup engineer" $log_file || \
       grep -q "Scanned 0 files" $log_file || \
       grep -q "Imported 0 events" $log_file; then
        echo "Detected error in logs, restarting the app..." >> /usr/src/app/logs/startup.log
        return 1
    else
        return 0
    fi
}

# Start the Node.js app
npm start >> /usr/src/app/logs/app_output.log 2>&1 &

# Monitor the logs and restart if necessary
while true; do
    sleep 120  # Check every 2 minutes
    if ! check_logs; then
        pkill -f "node src/service/main.js"
        npm start >> /usr/src/app/logs/app_output.log 2>&1 &
    fi
done

supervisord.conf

[supervisord]
nodaemon=true

[program:icarus]
command=/usr/src/app/start-app.sh
stdout_logfile=/usr/src/app/logs/supervisor_stdout.log
stderr_logfile=/usr/src/app/logs/supervisor_stderr.log
autostart=true
autorestart=true
startretries=3
startsecs=5

Project Structure

icarus-docker/
├── .env
├── Dockerfile
├── start-app.sh
└── supervisord.conf

I hope this can be useful to others. Keep up the amazing work!

Cheers,
goffy59


iaincollins commented 2 months ago

Oh this is amazing, thank you for putting so much work into this.

I had thought about this but I wasn't previously bothered to do it given what I thought would be a very small number of people, but folks have logged the issue here #55 and even messaged me directly about it.

Even if I can resolve the issue this is really nice to have, I will see if I can get it merged it.

I am also happy to open up Pull Request access. I had previously disabled that as I wasn't in a position to be able to accept / review requests at the time (just enough free time to work on the project, not enough time for that!) but things are bit different now and would be happy to accept changes!

goffy59 commented 2 months ago

Hey Iain,

Thanks for the kind words! I'm glad the Docker setup and SSHFS script were helpful.

I use SSHFS mainly for the security, but I understand it can be a bit slow and tricky to set up. Samba might be a better choice for most users, especially those on both Linux and Windows, since it’s generally easier and faster. I just wanted to share what I’ve got in case it helps anyone looking for a more secure setup.

Feel free to use or tweak it as you like. If you need more info, just let me know—I’m happy to help if I can. While I’m not an expert in Dockerizing entire projects from GitHub, the Dockerfile I shared should be pretty close to what other projects use for Docker deployment. You might want to double-check for best practices, but it’s a solid starting point.

Thanks again for all your hard work on this!

Cheers, goffy59

edit:

if you want to simply run it locally just use this run -d command as long as you have the other files. This is useful for issue #55 people having issues running it regularly. Try it inside a container instead so you don't need to worry about versions or prereq. YMMV I am not a coder... just know enough to break stuff and have fun, but it seems to work generally pretty good for me and every now and again I restart the container.

restart container= docker restart icarus-terminal stop container=docker stop icarus-terminal remove container from docker= docker remove icarus-terminal list containers= docker ps

docker run -d --name icarus-terminal --cap-add SYS_ADMIN \ -v (your path to elite dangerous log journal but remove the parenthesis ):/usr/src/app/logs \ -e LOG_DIR=/usr/src/app/logs \ -p 3300:3300 \ --restart always \ icarus-terminal

make sure docker is installed and all files i mentioned above are in the same directory. Let me know if you need clarification. Ignore the samba sshfs stuff if you intend to run it locally as I've explained here.