Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Containerized remote development workspaces #2390

Open
wants to merge 67 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
90c70ba
feat(devbox): Bootstrap code.
arunmathaisk Oct 11, 2024
69c3f46
feat(devboxes): create a directory called devboxes inside /home/frappe/
arunmathaisk Oct 18, 2024
db49dc2
fix(devbox): add property job setter
arunmathaisk Oct 18, 2024
6bc4f54
feat(devboxes): Added Jobs and made changes to the Devbox doctype
arunmathaisk Oct 21, 2024
c2efb07
Merge branch 'frappe:master' into master
arunmathaisk Oct 21, 2024
fa56630
feat(devbox): process job updates. added few doctype fields as well t…
arunmathaisk Oct 22, 2024
02149ab
feat(devboxes): tracking machine status
arunmathaisk Oct 22, 2024
7c9eb9c
feat(devbox): add go to devbox link on desk
arunmathaisk Oct 22, 2024
f2861ec
feat(devboxes): persist websockify port on sucessful running
arunmathaisk Oct 22, 2024
ef14403
Merge branch 'frappe:master' into master
arunmathaisk Oct 23, 2024
a0f6707
fix(devbox): sync status
arunmathaisk Oct 23, 2024
04fe4b4
fix(devbox): process job updates
arunmathaisk Oct 23, 2024
f8f8081
fix(ruff): ci was breaking
arunmathaisk Oct 23, 2024
f457057
style(ruff): was breaking ci
arunmathaisk Oct 23, 2024
0ad1b78
feat(devboxes): wip added dockerfile to build devboxes
arunmathaisk Oct 29, 2024
b669229
Merge branch 'master' into master
arunmathaisk Oct 29, 2024
611690d
feat(devboxes): install bench dependencies
arunmathaisk Oct 30, 2024
2e8e8c0
Merge branch 'frappe:master' into master
arunmathaisk Oct 30, 2024
7217ef5
fix(devbox image): working image with proper perms
arunmathaisk Nov 4, 2024
ced6cd5
fix(devbox-image): remove fiile
arunmathaisk Nov 4, 2024
afd5ff4
feat(devbox-image): with athuentication a truntime
arunmathaisk Nov 4, 2024
fb4e01b
Merge branch 'frappe:master' into master
arunmathaisk Nov 4, 2024
0adf86a
chore(devbox): readme
arunmathaisk Nov 4, 2024
be54a12
chore(devbox): readme
arunmathaisk Nov 4, 2024
a9d5fe7
chore(devbox): readme
arunmathaisk Nov 4, 2024
ad9d744
chore(devbox): readme
arunmathaisk Nov 4, 2024
5ff7efc
Merge branch 'frappe:master' into master
arunmathaisk Nov 5, 2024
c7c7628
Merge branch 'frappe:master' into master
arunmathaisk Nov 5, 2024
9e50bf4
feat(devboxes): adding code server and made changes to desk spin up …
arunmathaisk Nov 5, 2024
4ce5cb1
chore(devboxes): send all required params to start devbox
arunmathaisk Nov 14, 2024
92312d7
Merge remote-tracking branch 'origin/master'
arunmathaisk Dec 10, 2024
65dab97
Merge branch 'frappe:master' into master
arunmathaisk Dec 10, 2024
9586a35
feat(ui): Add DevBoxes in side bar
arunmathaisk Dec 10, 2024
d4f73cd
Merge branch 'frappe:master' into master
arunmathaisk Dec 12, 2024
d2a2465
chore(devbox): code-server-auth
arunmathaisk Dec 12, 2024
231d537
feat(devbox): store docker volume sizes
arunmathaisk Dec 12, 2024
af396c5
Merge branch 'frappe:master' into master
arunmathaisk Dec 12, 2024
535d08d
feat(devbox): sync all devboxes
arunmathaisk Dec 13, 2024
8ad1b76
feat(devbox): Destroy Devbox
arunmathaisk Dec 13, 2024
84d3ffa
chore(Devbox): added team field and rearranged fields
arunmathaisk Dec 16, 2024
187f18d
fix(devbox) : check for domain existence while new site and new devbox
arunmathaisk Dec 17, 2024
4d39c32
chore(devbox): field cleanups
arunmathaisk Dec 20, 2024
78ec224
fix(devbox): no need to run bench role if said server is a devbox server
arunmathaisk Dec 23, 2024
7a52e57
fix(devbox): sane port assignmnet, remove dumb methods, more precise …
arunmathaisk Dec 23, 2024
df341ab
Merge branch 'master' into mayday
arunmathaisk Dec 27, 2024
6c4d316
fix(merge-conflict): Re-added omitted code which somehow got deleted …
arunmathaisk Dec 27, 2024
f14d0e1
Merge branch 'frappe:master' into mayday
arunmathaisk Dec 30, 2024
ede38dc
Merge branch 'frappe:master' into mayday
arunmathaisk Dec 31, 2024
47ade4b
Merge branch 'frappe:master' into mayday
arunmathaisk Jan 1, 2025
bbfcb9a
fix(devbox): added agent job as fixtures and fixed lint issues with t…
arunmathaisk Jan 1, 2025
b59522f
feat(devboxes): Added new doctype devbox image to track images
arunmathaisk Jan 1, 2025
6930462
feat(devbox): Link devbox to devbox image doctype
arunmathaisk Jan 1, 2025
a530d32
fix(devbox): Fetch all servers that are not devbox servers
arunmathaisk Jan 2, 2025
3ff450b
Merge branch 'master' into mayday
arunmathaisk Jan 2, 2025
11d8e87
ci: Update .cspell.json
arunmathaisk Jan 2, 2025
8b532af
Merge branch 'master' into mayday
arunmathaisk Jan 2, 2025
53bdd96
Merge branch 'master' into mayday
arunmathaisk Jan 2, 2025
1a245cb
Merge branch 'frappe:master' into mayday
arunmathaisk Jan 3, 2025
2a75568
Merge branch 'master' into mayday
arunmathaisk Jan 6, 2025
fedd305
fix(proxy): added flag for proxy being solely for devbox xluster
arunmathaisk Jan 24, 2025
34888b4
feat(devbox): add cluster field and create dns record
arunmathaisk Jan 24, 2025
9427826
Merge branch 'master' into mayday
arunmathaisk Jan 30, 2025
1270d7d
fix(ruff): Reverting untouched files
arunmathaisk Jan 30, 2025
59d11b9
fix(ruff) Formatting bench_dependency
arunmathaisk Jan 30, 2025
eb8a842
fixUpdate role.json
arunmathaisk Jan 30, 2025
118018c
fix(ruff): Reverting untouched files
arunmathaisk Jan 30, 2025
bbc490c
Merge branch 'frappe:master' into mayday
arunmathaisk Jan 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,9 @@
"venv",
"vetur",
"Vetur",
"devbox",
"devboxes",
"websockify",
"Vevay",
"vfat",
"vimrc",
Expand Down Expand Up @@ -483,4 +486,4 @@
"sdg",
"asrc"
]
}
}
7 changes: 7 additions & 0 deletions dashboard/src2/components/NavigationItems.vue
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,13 @@ export default {
),
disabled: enforce2FA
},
{
name: 'Dev Boxes',
icon: () => h(Package),
route: '/devboxes',
condition: this.$team.doc?.devboxes_enabled,
disabled: enforce2FA
},
{
name: 'Billing',
icon: () => h(WalletCards),
Expand Down
134 changes: 134 additions & 0 deletions devbox-dockerfile/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
FROM debian:12-slim

ENV DEBIAN_FRONTEND=noninteractive \
LANG=en_US.UTF-8 \
LC_ALL=C.UTF-8 \
PASSWORD=password \
VNC_PASSWORD=password

# Install required packages
RUN apt-get update && apt-get install -y \
xfce4 \
xfce4-terminal \
tigervnc-standalone-server \
tigervnc-common \
novnc \
websockify \
supervisor \
curl \
wget \
git \
net-tools \
procps \
xauth \
dbus-x11 \
firefox-esr \
mariadb-server \
mariadb-client \
python3-dev \
python3-pip \
redis-server \
xvfb \
libfontconfig \
wkhtmltopdf \
sudo \
x11-xserver-utils \
xfonts-base \
pm-utils \
pulseaudio \
dbus-x11 \
policykit-1-gnome \
python3-venv \
cron \
locales \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& locale-gen en_US.UTF-8

# Configure MariaDB root password
RUN service mariadb start && \
mysqladmin -u root password 'frappe' && \
mysql -u root -pfrappe -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY 'frappe' WITH GRANT OPTION; FLUSH PRIVILEGES;"

# Add frappe user and add to sudoers
RUN useradd -m -s /bin/bash frappe && \
echo "frappe:password" | chpasswd && \
usermod -aG sudo frappe && \
echo "frappe ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers

# Create necessary directories and set permissions
RUN mkdir -p /home/frappe/.config /home/frappe/.vnc /home/frappe/.local && \
mkdir -p /var/log/supervisor && \
mkdir -p /run/user/1000 && \
mkdir -p /var/run/dbus && \
mkdir -p /var/lib/dbus && \
touch /home/frappe/.Xauthority && \
dbus-uuidgen > /var/lib/dbus/machine-id && \
chown -R frappe:frappe /home/frappe && \
chown -R frappe:frappe /var/log/supervisor && \
chown -R frappe:frappe /run/user/1000 && \
chmod -R 755 /home/frappe/.config && \
chmod -R 755 /home/frappe/.local && \
chmod 700 /run/user/1000 && \
chmod 755 /var/run/dbus && \
chmod -R 755 /var/lib/dbus

# Set up VNC configuration
RUN mkdir -p /home/frappe/.vnc && \
echo "#!/bin/bash\n\
export XDG_SESSION_TYPE=x11\n\
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/dbus/system_bus_socket\n\
export XDG_RUNTIME_DIR=/run/user/1000\n\
unset SESSION_MANAGER\n\
unset DBUS_SESSION_BUS_ADDRESS\n\
exec dbus-launch --exit-with-session startxfce4" > /home/frappe/.vnc/xstartup && \
chmod +x /home/frappe/.vnc/xstartup && \
chown -R frappe:frappe /home/frappe/.vnc

# Install bench CLI
RUN pip3 install frappe-bench --break-system-packages

# Switch to frappe user for remaining operations
USER frappe
WORKDIR /home/frappe
ENV PATH="/home/frappe/.local/bin:$PATH"

# Install NVM, Node.js, and Yarn
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash && \
export NVM_DIR="/home/frappe/.nvm" && \
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && \
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" && \
echo 'export NVM_DIR="$HOME/.nvm"' >> ~/.bashrc && \
echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> ~/.bashrc && \
echo '[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"' >> ~/.bashrc && \
. ~/.bashrc && \
nvm install 18 && \
nvm use 18 && \
nvm alias default 18 && \
npm install -g yarn

# Install code-server
RUN curl -fsSL https://code-server.dev/install.sh | sh

# Create code-server config directory and default config
RUN mkdir -p /home/frappe/.config/code-server && \
echo "bind-addr: 0.0.0.0:8443\n\
auth: password\n\
cert: false" > /home/frappe/.config/code-server/config.yaml

# Copy supervisor configuration and startup script
COPY --chown=frappe:frappe supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY --chown=frappe:frappe start.sh /home/frappe/start.sh
RUN chmod +x /home/frappe/start.sh

# Set environment variables
ENV NVM_DIR=/home/frappe/.nvm \
PATH="/home/frappe/.nvm/versions/node/v18/bin:/home/frappe/.local/bin:${PATH}" \
XDG_RUNTIME_DIR=/run/user/1000 \
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/dbus/system_bus_socket

# Expose ports
EXPOSE 6969 8443 5901

# Set the default command
CMD ["/home/frappe/start.sh"]
32 changes: 32 additions & 0 deletions devbox-dockerfile/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
### Create the volumes for persistence

```shell
docker volume create db-data

docker volume create home
```

### Build

```shell
docker build -t your_image_name .
```

### Run

6969 is for NOVNC \
8443 is for VSCode Server \
5901 is for Bare VNC Port

```
docker run -d \
-p 6969:6969 \
-p 8443:8443 \
-p 5901:5901 \
-v db-data:/var/lib/mysql \
-v home:/home/frappe \
-e PASSWORD="your_code_server_password" \
-e VNC_PASSWORD="your_vnc_password" \
your_image_name

```
56 changes: 56 additions & 0 deletions devbox-dockerfile/start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/bin/bash

# Stop VNC server if running
pkill Xtigervnc || true

# Clean up only specific X server files
rm -f /tmp/.X1-lock /tmp/.X11-unix/X1 || true

# Start dbus daemon using sudo
sudo dbus-daemon --system --nofork --nopidfile &

# Wait for DBus to start properly
sleep 2

# Check if DBus is running
if ! pgrep -x "dbus-daemon" > /dev/null; then
echo "Error: dbus-daemon failed to start!"
exit 1
fi

# Initialize Xauthority
touch ~/.Xauthority
chmod 600 ~/.Xauthority

# Validate and set VNC password
if [ ! -z "$VNC_PASSWORD" ]; then
if [ ${#VNC_PASSWORD} -lt 6 ]; then
echo "Error: VNC password must be at least 6 characters long"
exit 1
fi
echo "$VNC_PASSWORD" | vncpasswd -f > ~/.vnc/passwd
chmod 600 ~/.vnc/passwd
fi

# Validate and set code-server password
if [ ! -z "$PASSWORD" ]; then
if [ ${#PASSWORD} -lt 6 ]; then
echo "Error: Code-server password must be at least 6 characters long"
exit 1
fi
mkdir -p ~/.config/code-server
echo "bind-addr: 0.0.0.0:8443
auth: password
password: $PASSWORD
cert: false" > ~/.config/code-server/config.yaml
chmod 600 ~/.config/code-server/config.yaml
fi

# Start VNC server
if ! vncserver :1 -geometry 1280x800 -depth 24 -localhost no -xstartup ~/.vnc/xstartup; then
echo "Error: VNC server failed to start!"
exit 1
fi

# Start supervisord
exec supervisord -n -c /etc/supervisor/conf.d/supervisord.conf
76 changes: 76 additions & 0 deletions devbox-dockerfile/supervisord.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
[supervisord]
nodaemon=true
user=frappe
logfile=/var/log/supervisor/supervisord.log
pidfile=/run/user/1000/supervisord.pid

[program:dbus]
priority=1
command=sudo /usr/bin/dbus-daemon --system --nofork --nopidfile
user=frappe
startsecs=5
autostart=true
autorestart=true

[program:vncserver]
priority=10
directory=/home/frappe
command=vncserver :1 -geometry 1280x800 -depth 24 -localhost no -xstartup /home/frappe/.vnc/xstartup
user=frappe
environment=HOME="/home/frappe",USER="frappe",DISPLAY=":1",XDG_RUNTIME_DIR="/run/user/1000",LANG="en_US.UTF-8",LC_ALL="C.UTF-8",DBUS_SESSION_BUS_ADDRESS="unix:path=/run/dbus/system_bus_socket"
autostart=true
autorestart=true
startsecs=5
startretries=5
stderr_logfile=/var/log/supervisor/vncserver.stderr.log
stdout_logfile=/var/log/supervisor/vncserver.stdout.log
stopasgroup=true
killasgroup=true

[program:novnc]
priority=20
directory=/usr/share/novnc
command=/usr/bin/websockify --web=/usr/share/novnc 6969 localhost:5901
user=frappe
environment=HOME="/home/frappe",USER="frappe"
autostart=true
autorestart=true
startsecs=5
startretries=3
stderr_logfile=/var/log/supervisor/novnc.stderr.log
stdout_logfile=/var/log/supervisor/novnc.stdout.log

[program:code-server]
priority=30
directory=/home/frappe
command=/usr/bin/code-server --config /home/frappe/.config/code-server/config.yaml
user=frappe
environment=HOME="/home/frappe",USER="frappe",XDG_DATA_HOME="/home/frappe/.local/share",XDG_CONFIG_HOME="/home/frappe/.config"
autostart=true
autorestart=true
startsecs=5
startretries=3
stderr_logfile=/var/log/supervisor/code-server.stderr.log
stdout_logfile=/var/log/supervisor/code-server.stdout.log

[program:redis]
priority=40
command=sudo /usr/bin/redis-server
user=frappe
autostart=true
autorestart=true
startsecs=5
startretries=3
stderr_logfile=/var/log/supervisor/redis.stderr.log
stdout_logfile=/var/log/supervisor/redis.stdout.log

[program:mariadb]
priority=50
command=sudo /usr/bin/mysqld_safe
user=frappe
autostart=true
autorestart=true
startsecs=5
startretries=3
stderr_logfile=/var/log/supervisor/mariadb.stderr.log
stdout_logfile=/var/log/supervisor/mariadb.stdout.log
2 changes: 2 additions & 0 deletions press/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,7 @@ def create_agent_job(
bench=None,
site=None,
code_server=None,
devbox=None,
upstream=None,
host=None,
reference_doctype=None,
Expand Down Expand Up @@ -1009,6 +1010,7 @@ def create_agent_job(
"host": host,
"site": site,
"code_server": code_server,
"devbox": devbox,
"upstream": upstream,
"status": "Undelivered",
"request_method": method,
Expand Down
3 changes: 2 additions & 1 deletion press/api/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -1581,9 +1581,10 @@

@frappe.whitelist()
def exists(subdomain, domain):
from press.press.doctype.devbox.devbox import Devbox

Check warning on line 1584 in press/api/site.py

View check run for this annotation

Codecov / codecov/patch

press/api/site.py#L1584

Added line #L1584 was not covered by tests
from press.press.doctype.site.site import Site

return Site.exists(subdomain, domain)
return Site.exists(subdomain, domain) or Devbox.exists(subdomain, domain)

Check warning on line 1587 in press/api/site.py

View check run for this annotation

Codecov / codecov/patch

press/api/site.py#L1587

Added line #L1587 was not covered by tests


@frappe.whitelist()
Expand Down
Loading
Loading