
Running GraphWeather on Linux: Wine, Mono or Docker
Three practical approaches to running GraphWeather on Linux β Wine for the desktop app, Mono for .NET components, and Docker for isolated deployments.
GraphWeather is a Windows application. That is a fact, not a limitation β provided you are willing to meet it halfway. I have been running GraphWeather on Linux servers for the better part of four years, across three different approaches, and each one solves a slightly different problem. Wine gives you the full desktop experience. Mono handles the .NET helper tools. Docker wraps everything in an isolated, reproducible container. This guide walks through all three so you can pick the one that fits your infrastructure.
If you have not yet decided whether GraphWeather is the right tool for your setup, the three-way comparison with Weewx and CumulusMX will help you weigh the options before investing time in a Linux deployment. And if you just want the GraphWeather overview, start there.
Quick-Answer Summary
| Approach | Best for | Complexity | Serial/USB support |
|---|---|---|---|
| Wine | Full desktop app on a Linux workstation | Medium | Yes, with configuration |
| Mono | Running .NET helper tools only (not the main app) | Low | N/A (tools only) |
| Docker | Headless server, CI/CD, reproducible deployments | Medium-high | Possible but fiddly |
If you want the fastest path to a working setup and your station connects via USB: Wine on a dedicated Linux box. If you want maximum isolation and your data arrives via network (IP logger, MQTT, or CSV import): Docker.
Prerequisites
Regardless of which approach you choose, you will need:
- A Linux distribution from the past three years. Debian 12, Ubuntu 22.04+, Fedora 38+, and Raspberry Pi OS (64-bit) are all tested.
- Root or sudo access for package installation.
- The GraphWeather installer (
.exe) downloaded from the GraphWeather page. - At least 2 GB of free disk space (Wine alone pulls in several hundred megabytes of dependencies).
- For USB station connections: the station physically attached to the Linux machine, with the appropriate kernel driver loaded (most Davis and Fine Offset stations use
cp210xorch341).
Approach 1 β Wine
Wine translates Windows API calls into POSIX calls at runtime. It is not an emulator β it is a compatibility layer, and for a well-behaved C++ desktop application like GraphWeather, it works remarkably well.
Step 1: Install Wine
On Debian/Ubuntu:
sudo dpkg --add-architecture i386
sudo apt update
sudo apt install wine64 wine32 winetricks
On Fedora:
sudo dnf install wine winetricks
Confirm the version:
wine --version
You want Wine 8.0 or later. Earlier versions have known issues with the GDI rendering that GraphWeather uses for its real-time gauge display.
Step 2: Configure the Wine Prefix
Create a dedicated prefix for GraphWeather to keep it isolated from any other Wine applications:
export WINEPREFIX="$HOME/.wine-graphweather"
export WINEARCH=win64
wineboot --init
Install the Visual C++ runtime (GraphWeather links against it):
winetricks vcrun2019
If GraphWeather's installer also requires .NET components for helper tools, add:
winetricks dotnet48
This step can take ten to fifteen minutes. Winetricks downloads and installs the actual Microsoft runtimes inside the Wine prefix.
Step 3: Install GraphWeather
wine GraphWeather_Setup_2.0.308b.exe
Follow the installer prompts. The default installation path maps to $WINEPREFIX/drive_c/Program Files/GraphWeather/. After installation, launch it:
wine "$WINEPREFIX/drive_c/Program Files/GraphWeather/GraphWeather.exe"
The main window should appear. If it does not, check $WINEPREFIX/drive_c/users/$USER/Temp/ for log files, or run with WINEDEBUG=+relay for verbose output (warning: this produces enormous logs).
Step 4: Serial/USB Passthrough
This is where most people get stuck. Wine maps Linux serial devices to COM ports, but you have to tell it which device maps to which port.
Create a symbolic link inside the Wine prefix:
ln -s /dev/ttyUSB0 "$WINEPREFIX/dosdevices/com1"
Replace /dev/ttyUSB0 with your station's actual device node. Find it with:
dmesg | grep tty
Ensure your user is in the dialout group:
sudo usermod -aG dialout $USER
Log out and back in (or newgrp dialout). In GraphWeather's station configuration, select COM1 as the port.
Step 5: Run as a Service
For unattended operation, create a systemd service:
# /etc/systemd/system/graphweather.service
[Unit]
Description=GraphWeather via Wine
After=network.target
[Service]
User=weather
Environment=WINEPREFIX=/home/weather/.wine-graphweather
Environment=DISPLAY=:0
ExecStart=/usr/bin/wine "/home/weather/.wine-graphweather/drive_c/Program Files/GraphWeather/GraphWeather.exe"
Restart=on-failure
RestartSec=30
[Install]
WantedBy=multi-user.target
The DISPLAY=:0 environment variable is necessary because GraphWeather is a GUI application. On a headless server, use Xvfb (a virtual framebuffer) instead:
sudo apt install xvfb
Change the ExecStart line to:
ExecStart=/usr/bin/xvfb-run -a /usr/bin/wine "/home/weather/.wine-graphweather/drive_c/Program Files/GraphWeather/GraphWeather.exe"
Enable and start the service:
sudo systemctl enable graphweather
sudo systemctl start graphweather
Known Wine Quirks
- Font rendering: Some dialog labels may appear truncated. Install
winetricks corefontsto fix most cases. - High-DPI displays: The gauge rendering can scale incorrectly. Set the Wine DPI override:
wine reg add "HKCU\\Control Panel\\Desktop" /v LogPixels /t REG_DWORD /d 96 /f. - Audio warnings: GraphWeather can play audio alerts for extreme conditions. Wine's audio subsystem requires PulseAudio or ALSA configuration. If you do not need audio alerts, disable them in GraphWeather's settings to avoid error messages in the Wine log.
Approach 2 β Mono for .NET Helper Tools
GraphWeather's core is C++, but some helper tools (data migration utilities, configuration editors) are .NET assemblies. If you only need these tools β not the full desktop application β Mono runs them natively on Linux without Wine.
Install Mono
sudo apt install mono-complete
Run a .NET tool:
mono GraphWeatherDataTool.exe --import data.csv
Mono does not support Windows Forms rendering as well as Wine does, so GUI-based tools may have visual glitches. For command-line utilities, though, it works flawlessly.
This approach is most useful when your main GraphWeather instance runs on a Windows machine and you want to run data processing or migration scripts on a Linux server. For the template and plugin side of things, the custom templates and plugin development guide explains what you can build on the Windows side; the Mono approach lets you run the data pipeline components on Linux.
Approach 3 β Docker
Docker gives you the strongest isolation and the most reproducible deployments. The trade-off is complexity β especially around USB device access.
Dockerfile
FROM scottyhardy/docker-wine:stable
# Install GraphWeather
COPY GraphWeather_Setup_2.0.308b.exe /tmp/
RUN xvfb-run wine /tmp/GraphWeather_Setup_2.0.308b.exe /S && \
rm /tmp/GraphWeather_Setup_2.0.308b.exe
# Create data directories
RUN mkdir -p /data/export /data/config
# Copy default configuration
COPY graphweather.ini /root/.wine/drive_c/Program\ Files/GraphWeather/
VOLUME ["/data/export", "/data/config"]
CMD ["xvfb-run", "wine", "/root/.wine/drive_c/Program Files/GraphWeather/GraphWeather.exe"]
The scottyhardy/docker-wine base image bundles Wine with Xvfb and the necessary 32-bit libraries. The /S flag runs the GraphWeather installer in silent mode.
Docker Compose
version: "3.9"
services:
graphweather:
build: .
volumes:
- ./export:/data/export
- ./config:/data/config
devices:
- /dev/ttyUSB0:/dev/ttyUSB0
restart: unless-stopped
The devices key passes the USB serial device into the container. This requires the container to run with sufficient privileges β --privileged in the worst case, or more targeted capability grants:
cap_add:
- SYS_RAWIO
security_opt:
- apparmor:unconfined
USB Device Access from Containers
This is the hardest part of the Docker approach. The device node must exist when the container starts, which means:
- The station must be plugged in before you run
docker compose up. - If the station disconnects and reconnects, the device node may change (e.g.,
/dev/ttyUSB0becomes/dev/ttyUSB1). Use a udev rule to create a stable symlink:
# /etc/udev/rules.d/99-weather-station.rules
SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", SYMLINK+="weatherstation"
Replace the vendor and product IDs with your station's values (find them with lsusb). Then mount /dev/weatherstation in the Compose file.
Scheduling with Cron Inside the Container
GraphWeather has its own internal scheduler, so you typically do not need cron for data collection. However, if you want to trigger periodic maintenance tasks (log rotation, backup exports), add a cron job to the Docker image:
RUN apt-get update && apt-get install -y cron
COPY crontab /etc/cron.d/graphweather-cron
RUN chmod 0644 /etc/cron.d/graphweather-cron && crontab /etc/cron.d/graphweather-cron
A simpler alternative: keep maintenance tasks outside the container and operate on the mounted volumes from the host.
Performance Comparison
| Approach | CPU overhead | Memory | Startup time |
|---|---|---|---|
| Wine (bare metal) | ~5% above native Windows | ~150 MB | 3-5 seconds |
| Mono (tools only) | Negligible | ~50 MB | 1-2 seconds |
| Docker + Wine | ~8% above native Windows | ~300 MB (container + Wine) | 10-15 seconds |
For a dedicated weather-station server, all three approaches are well within the capabilities of a Raspberry Pi 4 (4 GB model). On a Pi 3, the Docker approach is tight on memory β stick with bare-metal Wine.
If you are already running a Grafana stack for visualisation β as described in the Grafana dashboard guide β Docker Compose lets you manage GraphWeather, Telegraf, InfluxDB, and Grafana as a single stack. That operational simplicity can outweigh the USB complexity.
Common Mistakes
- Wine version too old. Distributions sometimes ship ancient Wine packages. GraphWeather needs Wine 8.0+ for reliable GDI rendering. Use the WineHQ repository for up-to-date packages if your distro's version is behind.
- Missing 32-bit libraries. Even on a 64-bit system, Wine needs 32-bit libraries (
lib32-packages ori386architecture). The symptom is a cryptic "Bad EXE format" error. Rundpkg --add-architecture i386 && apt update && apt install wine32to fix it. - Docker volume permission issues. Files written by Wine inside the container are owned by the Wine user (usually root). If you mount a host directory, set permissions with
chownor run the container with--user $(id -u):$(id -g). - Forgetting Xvfb on headless systems. GraphWeather will not start without a display.
xvfb-runcreates a virtual framebuffer that satisfies the requirement without a physical monitor. - USB device disappearing after reboot. If you hard-code
/dev/ttyUSB0in your config and the device enumerates differently after a reboot, GraphWeather will not find the station. Always use a udev symlink for stable device naming.
Related Reading
- GraphWeather overview β features, download, getting started.
- Publishing your weather pages β once GraphWeather is running on Linux, push your pages to a web host.
- FTP publishing guide β protocol configuration for publishing from a Linux-based GraphWeather installation.
- Build a Grafana Weather Dashboard β combine Docker-based GraphWeather with a Grafana stack.
- GraphWeather vs. Weewx vs. CumulusMX β if the Linux setup seems too involved, Weewx may be a more natural fit.
- Custom Templates & Plugin Development β build templates and plugins on the Windows side, deploy on Linux.
FAQ
Does GraphWeather run on ARM Linux (Raspberry Pi)?
Yes, via the wine-arm package or the box86/box64 translation layer. Performance is acceptable on a Pi 4. On a Pi 3, expect slow startup and occasional GUI lag β but the data collection and publishing pipeline runs fine once it stabilises.
Can I run GraphWeather in WSL2 instead of full Linux?
WSL2 is technically Linux, but it adds its own layer of complexity for USB passthrough (you need usbipd-win). If your host is Windows, just run GraphWeather natively β WSL2 adds overhead without benefit in this scenario.
Which approach is most reliable for 24/7 unattended operation?
Wine as a systemd service with Xvfb. It has the fewest moving parts and recovers cleanly from crashes via systemd's Restart=on-failure directive. Docker is a close second if you already operate a container infrastructure.
Can I access GraphWeather's GUI remotely when running under Xvfb?
Yes. Install a VNC server (e.g., x11vnc) and point it at the Xvfb display. You will be able to interact with GraphWeather's full interface from any VNC client. Alternatively, use xpra for a more responsive experience over high-latency connections.
Will future versions of GraphWeather support Linux natively? That is a question for the developer. The PHP web components already run natively on Linux. The C++ desktop application is the Windows-dependent piece. Based on the current architecture, a native Linux port would require significant effort, so Wine and Docker remain the practical path for the foreseeable future.