Initial commit
Some checks failed
Build a dev image / build (push) Has been cancelled

This commit is contained in:
Adam Štrauch 2025-09-27 00:25:22 +02:00
commit 8c81737b87
Signed by: cx
GPG key ID: 7262DAFE292BCE20
8 changed files with 326 additions and 0 deletions

21
.gitea/workflows/main.yml Normal file
View file

@ -0,0 +1,21 @@
name: Build a dev image
on:
push:
branches: [ main ]
jobs:
build:
runs-on: [dev, amd64]
env:
IMAGE: gitea.ceperka.net/rosti/mgm
TAG: dev
steps:
- uses: actions/checkout@v4
- name: docker login
run: |
docker login gitea.ceperka.net -u "${{ secrets.REPO_USERNAME }}" -p "${{ secrets.REPO_PASSWORD }}"
- name: Build
run: task build REPO=$IMAGE VERSION=$TAG
- name: Push
run: task push REPO=$IMAGE VERSION=$TAG

38
Dockerfile Normal file
View file

@ -0,0 +1,38 @@
FROM alpine:3.22
RUN apk update && apk upgrade && apk add --no-cache \
git \
docker \
bash \
fish \
zsh \
wget \
curl \
htop \
vim \
nano \
tmux \
openssh-server \
iproute2
# Download ttyd
RUN wget -O /usr/local/bin/ttyd https://github.com/tsl0922/ttyd/releases/download/1.7.7/ttyd.x86_64 && chmod +x /usr/local/bin/ttyd
# Configure SSH
RUN mkdir -p /var/run/sshd && \
sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config && \
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config
# Copy entrypoint script
COPY entrypoint.sh /app/
COPY service.ssh.sh /app/
COPY service.ttyd.sh /app/
RUN chmod +x /app/entrypoint.sh /app/service.ssh.sh /app/service.ttyd.sh
RUN mkdir -p /srv/stack
WORKDIR /srv/stack
EXPOSE 22 1234
ENTRYPOINT ["/app/entrypoint.sh"]

10
LICENCE Normal file
View file

@ -0,0 +1,10 @@
Copyright (c) 2025, Roští.cz, s.r.o. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the Roští.cz, s.r.o.
Neither the name of the Roští.cz, s.r.o. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY Roští.cz, s.r.o. AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Roští.cz, s.r.o. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

162
README.md Normal file
View file

@ -0,0 +1,162 @@
# MGM Image
A lightweight Alpine-based Docker image that provides SSH and web terminal access through ttyd. Perfect for development environments, remote debugging, or containerized workspaces.
## Features
- 🐧 **Alpine Linux** - Minimal base image for small footprint
- 🔒 **SSH Server** - Full SSH access on port 22
- 🌐 **Web Terminal** - Browser-based terminal via ttyd on port 1234
- 🐚 **Fish Shell** - Modern shell with auto-suggestions and syntax highlighting
- 🔧 **Development Tools** - Git, curl, wget, htop, vim, nano included
- 🚦 **Signal Handling** - Proper Docker signal propagation for graceful shutdowns
## Quick Start
### Environment Variables
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `TTYD_PASSWORD` | ✅ Yes | - | Password for web terminal authentication |
### Running the Container
```bash
docker run -d \
--name mgm-container \
-p 2222:22 \
-p 1234:1234 \
-e TTYD_PASSWORD=your_secure_password \
gitea.ceperka.net/rosti/mgm:dev
```
### Accessing Services
- **SSH**: `ssh root@localhost -p 2222`
- **Web Terminal**: http://localhost:1234 (username: `tty`, password: your `TTYD_PASSWORD`)
## Building
This project uses [Task](https://taskfile.dev) for build automation.
### Prerequisites
- Docker
- Task (optional, you can use docker commands directly)
### Build Commands
```bash
# Build the image
task build
# Push to registry
task push
# Or use Docker directly
docker build -t gitea.ceperka.net/rosti/mgm:dev .
```
## Architecture
The container runs two services managed by a bash-based process supervisor:
```
entrypoint.sh
├── service.ssh.sh # SSH daemon (/usr/sbin/sshd -D)
└── service.ttyd.sh # Web terminal (ttyd + fish shell)
```
### Process Management
- **Signal Handling**: SIGTERM/SIGINT signals are properly propagated to child processes
- **Graceful Shutdown**: Services receive SIGTERM first, then SIGKILL after timeout
- **Process Monitoring**: Parent process waits for all children and handles exits
- **No Dependencies**: Pure bash implementation, no external process managers
### Security Considerations
- SSH is configured to allow root login with password authentication
- ttyd is bound to `127.0.0.1` (localhost) for security - use reverse proxy if needed
- Set a strong `TTYD_PASSWORD` as it protects web terminal access
- Consider using SSH keys instead of passwords in production
## Development
### File Structure
```
├── Dockerfile # Alpine-based image definition
├── entrypoint.sh # Main entrypoint with process management
├── service.ssh.sh # SSH service wrapper
├── service.ttyd.sh # ttyd service wrapper
├── Taskfile.yml # Build automation
└── README.md # This file
```
### Customization
You can extend this image for your specific needs:
```dockerfile
FROM gitea.ceperka.net/rosti/mgm:dev
# Add your tools
RUN apk add --no-cache python3 nodejs
# Copy your configurations
COPY custom-config/ /etc/
# Set your working directory
WORKDIR /workspace
```
## Troubleshooting
### Container won't start
1. Check if `TTYD_PASSWORD` is set:
```bash
docker logs <container-name>
```
2. Verify ports aren't already in use:
```bash
netstat -tulpn | grep -E ':(22|1234)'
```
### SSH connection refused
1. Check if SSH service is running:
```bash
docker exec <container-name> ps aux | grep sshd
```
2. Verify SSH host keys were generated:
```bash
docker exec <container-name> ls -la /etc/ssh/ssh_host_*
```
### Web terminal not accessible
1. Check ttyd service status:
```bash
docker exec <container-name> ps aux | grep ttyd
```
2. Verify ttyd is listening:
```bash
docker exec <container-name> netstat -tulpn | grep 1234
```
## Contributing
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
## License
This project is open source. Please check the license file for more details.

15
Taskfile.yml Normal file
View file

@ -0,0 +1,15 @@
# https://taskfile.dev
version: '3'
vars:
IMAGE: gitea.ceperka.net/rosti/mgm
TAG: dev
tasks:
build:
cmds:
- docker build -t {{ .IMAGE }}:{{ .TAG }} .
push:
cmds:
- docker push {{ .IMAGE }}:{{ .TAG }}

74
entrypoint.sh Normal file
View file

@ -0,0 +1,74 @@
#!/bin/bash
# Entrypoint script to start SSH and ttyd services
set -e
if [ -z "$TTYD_TOKEN" ]; then
echo "Warning: TTYD_TOKEN not set, exiting."
exit 1
fi
if [ -z "$SET_SHELL" ]; then
echo "Warning: SET_SHELL not set, using default '/bin/bash'."
export SET_SHELL="/bin/bash"
fi
echo "Initializing services..."
# Generate SSH host keys if they don't exist
if [ ! -f /etc/ssh/ssh_host_rsa_key ]; then
echo "Generating SSH host keys..."
ssh-keygen -A
fi
# Array to store child PIDs
declare -a CHILD_PIDS=()
# Function to handle shutdown gracefully
shutdown_handler() {
echo "Shutting down services..."
# Send SIGTERM to all child processes
for pid in "${CHILD_PIDS[@]}"; do
if kill -0 "$pid" 2>/dev/null; then
echo "Sending SIGTERM to PID: $pid"
kill -TERM "$pid" 2>/dev/null || true
fi
done
# Wait a bit for graceful shutdown
sleep 2
# Force kill any remaining processes
for pid in "${CHILD_PIDS[@]}"; do
if kill -0 "$pid" 2>/dev/null; then
echo "Force killing PID: $pid"
kill -KILL "$pid" 2>/dev/null || true
fi
done
echo "All services stopped"
exit 0
}
# Set up signal handlers
trap shutdown_handler SIGTERM SIGINT
# Start services in background and collect PIDs
echo "Starting services..."
echo "Starting SSH service..."
/app/service.ssh.sh &
CHILD_PIDS+=($!)
echo "SSH service started with PID: $!"
echo "Starting ttyd service..."
/app/service.ttyd.sh &
CHILD_PIDS+=($!)
echo "ttyd service started with PID: $!"
echo "Both services are running. PIDs: ${CHILD_PIDS[*]}"
# Wait for all background processes
wait

3
service.ssh.sh Normal file
View file

@ -0,0 +1,3 @@
#!/bin/sh
exec /usr/sbin/sshd -D

3
service.ttyd.sh Normal file
View file

@ -0,0 +1,3 @@
#!/bin/sh
exec /usr/local/bin/ttyd -p 1234 -b /$TTYD_TOKEN/terminal -w /srv/stack -W $SET_SHELL