This guide covers common problems, their causes, and solutions. Start by checking the error log with --log-level info to see detailed diagnostic messages.
Server fails to start with an error like:
Error: Address already in use
Bind failed on 127.0.0.1:8080
Another process is already listening on the same port.
Find the process using the port:
On macOS/Linux with lsof:
lsof -i :8080Output example:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python 1234 user 3u IPv4 0x1234... 0t0 TCP *:8080 (LISTEN)
On Linux with netstat:
netstat -tuln | grep :8080Kill or stop the conflicting process:
kill 1234Or use a different port:
./PureSimpleHTTPServer --port 8081Requesting a file returns 403 Forbidden, even though the file exists and is readable.
The file path is in a blocked list. PureSimpleHTTPServer hides sensitive files and directories by default:
.git— Version control metadata.env— Environment variables and secrets.DS_Store— macOS metadata.gitignore,.gitattributes— Git configuration- Files starting with a dot (hidden files on Unix)
Check if the file is hidden:
ls -la /path/to/fileIf the filename starts with a dot or is in the hidden list, either:
- Rename the file to a public name (recommended for secrets)
- Move it outside the web root (recommended for
.env) - Check your rewrite rules — they may be blocking the path incorrectly
To serve hidden files (use with caution):
./PureSimpleHTTPServer --allow-hidden-filesRequesting a file returns 404 Not Found, but the file clearly exists:
ls -la /var/www/file.html
# -rw-r--r-- file.htmlCommon causes:
- Wrong
--rootdirectory — The server is looking in the wrong place - Relative vs. absolute paths —
--root ./wwwvs.--root /var/www - File not under root — The file is outside the specified root directory
- Missing index file — Accessing a directory without index.html
Verify the root directory:
./PureSimpleHTTPServer --log-level info --root /var/wwwCheck the startup log:
[INFO] Server started with root: /var/www
Use absolute paths in production:
# Bad: relative path
./PureSimpleHTTPServer --root ./www
# Good: absolute path
./PureSimpleHTTPServer --root /var/wwwVerify the file is in root:
# If root is /var/www, the file must be at:
/var/www/file.html # OK
/var/file.html # NOT OK (outside root)Visiting / or a subdirectory shows a file listing instead of loading index.html.
PureSimpleHTTPServer is not finding an index.html file in the directory, so it falls back to showing a listing. This happens when:
- The index file doesn't exist
- The index file has a different name
- The index file is in the wrong location
Check for index.html:
ls -la /var/www/
# Should include: index.htmlCreate an index file if missing:
echo "<h1>Welcome</h1>" > /var/www/index.htmlVerify the filename:
PureSimpleHTTPServer looks specifically for index.html (lowercase). Ensure it's not named Index.html or index.htm.
Check subdirectories:
If you want a subdirectory to serve a landing page, add index.html to it:
echo "<h1>Subdir</h1>" > /var/www/docs/index.htmlA single-page application (SPA) works when navigating via internal links, but refreshing the browser on a deep route like /dashboard/settings shows 404 Not Found.
The browser requests /dashboard/settings from the server, but there's no actual file at that path. SPAs handle routing in JavaScript, so all requests should serve index.html to let the client-side router work.
Enable SPA mode:
./PureSimpleHTTPServer --root /var/www --spaWith --spa, all requests for missing files are rewritten to serve index.html, allowing your client-side router to handle the path.
This works for any path that isn't a real file:
/dashboard/settings -> index.html (rewritten)
/api/users -> index.html (rewritten, if no /api/users file exists)
/js/app.js -> app.js (served directly, file exists)
Visiting /about returns 404, but /about.html works.
You forgot to enable clean URLs, or the actual file doesn't have a .html extension.
Enable clean URLs:
./PureSimpleHTTPServer --root /var/www --clean-urlsWith --clean-urls, the server tries these in order:
/about -> /about.html (if it exists)
-> /about/index.html (if it exists)
-> 404 (if neither exists)
Verify files exist with .html extension:
ls -la /var/www/
# Must have: about.html (or about/index.html)Clean URLs cannot create or rename files—they only rewrite requests to existing .html files.
A rewrite rule in rewrite.conf isn't triggering; requests are returning 404 instead of being rewritten.
Common issues:
- Wrong pattern type — Using regex syntax in a simple pattern, or vice versa
- Missing leading slash — Pattern doesn't start with
/ - File exists — If the exact file exists, rewrite rules don't apply (rewrite is a fallback)
- Rule syntax error — Invalid regex or destination format
Enable info-level logging to see rule matching:
./PureSimpleHTTPServer --log-level info --root /var/wwwCheck the logs for rule evaluation:
[INFO] Evaluating rewrite rule: /api/* -> /api.php
[INFO] /api/users matched; rewriting to /api.php
[INFO] /static/app.css did not match
Check your rewrite.conf syntax:
Simple pattern example:
/api/* /api.php
Regex pattern example (with ^):
^/old/(.*) /new/$1
Verify the destination file exists:
# Rule: /api/* -> /api.php
ls -la /var/www/api.php
# Must exist and be readableTest patterns manually:
If your destination is /api.php, verify it's accessible directly:
curl http://localhost:8080/api.phpYou set --log /var/log/pshs/access.log, but the file isn't created; instead, the server shows a warning or fails to start.
- Directory doesn't exist —
/var/log/pshs/wasn't created - No write permission — The process user can't write to the directory
- Path error — Typo in the path
Create the log directory:
mkdir -p /var/log/pshsSet correct ownership and permissions:
Replace www-data with the user running the server:
chown www-data:www-data /var/log/pshs
chmod 750 /var/log/pshsVerify write permission:
touch /var/log/pshs/access.log
chmod 640 /var/log/pshs/access.logCheck the full path:
Use absolute paths; relative paths may not work as expected:
# Bad: relative
./PureSimpleHTTPServer --log ./logs/access.log
# Good: absolute
./PureSimpleHTTPServer --log /var/log/pshs/access.logThe server runs fine while the terminal is open, but stops as soon as you close the terminal or disconnect.
The process is attached to the terminal session. When the terminal exits, the process receives SIGHUP and terminates.
Use nohup:
nohup ./PureSimpleHTTPServer --root /var/www > /tmp/server.log 2>&1 &This detaches the process from the terminal.
Or use a service manager (recommended):
On systemd (Linux):
Create /etc/systemd/system/pshs.service:
[Unit]
Description=PureSimpleHTTPServer
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/pshs
ExecStart=/opt/pshs/PureSimpleHTTPServer --root /var/www --log /var/log/pshs/access.log
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.targetEnable and start:
sudo systemctl enable pshs
sudo systemctl start pshsOn launchd (macOS):
Create ~/Library/LaunchAgents/com.pshs.server.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.pshs.server</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/PureSimpleHTTPServer</string>
<string>--root</string>
<string>/var/www</string>
<string>--log</string>
<string>/var/log/pshs/access.log</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
</dict>
</plist>Load the agent:
launchctl load ~/Library/LaunchAgents/com.pshs.server.plistCPU usage spikes to 100% when handling many concurrent connections, even though the requests themselves are simple.
This is often normal behavior—handling many connections requires CPU work. However, logging can amplify this:
- Every request generates a log entry
- Disk I/O for logging is slower than request handling
- High concurrency means many log writes per second
Reduce logging overhead:
Use --log-level none to disable error logging and keep only access logs:
./PureSimpleHTTPServer --log /var/log/pshs/access.log --log-level noneOr disable access logging entirely if you don't need it (e.g., for internal APIs):
./PureSimpleHTTPServer --log-level warnMonitor actual bottleneck:
Use profiling tools to identify the real bottleneck:
# On macOS with Activity Monitor:
# 1. Start the server
# 2. Open Activity Monitor
# 3. Sort by CPU and check context switches, threads, I/OConsider your hardware:
High CPU on many concurrent connections is normal. Upgrade to a faster CPU or multi-core machine if needed.
Trying to run the server shows "Permission denied" or "command not found":
./PureSimpleHTTPServer
# bash: ./PureSimpleHTTPServer: Permission deniedThe binary doesn't have execute permission.
Add execute permission:
chmod +x ./PureSimpleHTTPServerVerify:
ls -la PureSimpleHTTPServer
# Should show: -rwxr-xr-x (executable bit set)The server is serving files from the wrong directory, or paths are being resolved incorrectly.
The --root path is relative or contains symlinks that resolve differently than expected.
Always use absolute paths in production:
# Bad
./PureSimpleHTTPServer --root ./www
# Good
./PureSimpleHTTPServer --root /var/wwwRelative paths depend on the current working directory, which can change. Absolute paths are unambiguous.
Check the actual root being used:
./PureSimpleHTTPServer --log-level info --root /var/www | head -20Look for the startup log message:
[INFO] Server started with root: /var/www
Verify symlinks resolve correctly:
If your root directory contains symlinks:
# See the real path
realpath /var/wwwTest a specific file:
curl http://localhost:8080/index.html -vThe log will show which file was actually served.
You ran kill -HUP $(cat /var/run/pshs.pid), but the log file wasn't reopened or logrotate still reports an error.
- PID file not set — The server was started without
--pid-file, so no PID file exists - Wrong PID — The PID file contains an old PID; the process isn't running
- Log file path — The server was started without
--log, so there are no logs to reopen
Start the server with --pid-file:
./PureSimpleHTTPServer \
--root /var/www \
--log /var/log/pshs/access.log \
--pid-file /var/run/pshs.pidVerify the PID file exists and is valid:
cat /var/run/pshs.pid
# Should output a number
ps aux | grep $(cat /var/run/pshs.pid)
# Should show the running processTest SIGHUP manually:
kill -HUP $(cat /var/run/pshs.pid)
echo "Exit code: $?"If the command shows "No such process", the PID is stale.
Check logrotate configuration:
Ensure /etc/logrotate.d/pshs references the correct PID file:
postrotate
kill -HUP $(cat /var/run/pshs.pid) 2>/dev/null || true
endscriptYou created a rewrite.conf file in a subdirectory, but the rules aren't being applied.
- File not inside
--root— Rewrite rules are only loaded from within the root directory - File not found — The path doesn't exist or is misspelled
- File not readable — The process user doesn't have read permission
- Old rules cached — The server loaded rules at startup; changes require a restart
Verify the file is in the root directory:
# If --root is /var/www
ls -la /var/www/subdir/rewrite.conf
# Must exist and be readableCheck file permissions:
chmod 644 /var/www/subdir/rewrite.confRestart the server to reload rules:
kill $(cat /var/run/pshs.pid)
./PureSimpleHTTPServer --root /var/www --log-level infoCheck startup logs for rewrite rules:
./PureSimpleHTTPServer --log-level info | grep -i rewriteYou should see:
[INFO] Loaded rewrite rules from /var/www/rewrite.conf
[INFO] Loaded rewrite rules from /var/www/subdir/rewrite.conf
If a file is missing, you'll see:
[WARN] Rewrite file not found: /var/www/subdir/rewrite.conf
Server fails to start with:
ERROR: Cannot read TLS certificate file: cert.pem
or
ERROR: Cannot read TLS key file: key.pem
The --tls-cert or --tls-key path does not point to a readable file, or both flags were not specified together.
Verify both files exist and are readable:
ls -la cert.pem key.pemBoth flags must be specified together:
# Wrong — only one flag
./PureSimpleHTTPServer --tls-cert cert.pem
# Correct — both flags
./PureSimpleHTTPServer --tls-cert cert.pem --tls-key key.pemUse absolute paths in production:
./PureSimpleHTTPServer --tls-cert /etc/ssl/certs/server.pem --tls-key /etc/ssl/private/server.keyServer fails to start with:
ERROR: Failed to obtain TLS certificate
Make sure acme.sh is installed (~/.acme.sh/acme.sh)
and port 80 is accessible from the internet
- acme.sh is not installed at
~/.acme.sh/acme.sh - Port 80 is blocked by a firewall or another process
- DNS is not configured — the domain doesn't resolve to this server's IP
Install acme.sh:
curl https://get.acme.sh | shCheck port 80 is available:
lsof -i :80If another process is using port 80, stop it or reconfigure it.
Verify DNS:
dig +short example.com
# Should return this server's public IPAuto-TLS fails because port 80 is already occupied (e.g., by Apache, nginx, or another web server).
The --auto-tls feature starts an HTTP listener on port 80 to serve ACME HTTP-01 challenge files and redirect other traffic to HTTPS. If port 80 is already in use, this fails.
Stop the process using port 80:
# Find and stop the conflicting process
lsof -i :80
sudo kill <PID>Or use manual TLS instead:
If you cannot free port 80, obtain your certificate separately and use manual TLS:
# Obtain cert with acme.sh standalone mode (temporarily binds port 80)
~/.acme.sh/acme.sh --issue -d example.com --standalone
# Then start with manual TLS
./PureSimpleHTTPServer --port 443 \
--tls-cert ~/.acme.sh/example.com_ecc/fullchain.cer \
--tls-key ~/.acme.sh/example.com_ecc/example.com.keyThe server logs show renewal errors, or after 90 days the certificate expires.
The background renewal thread checks every 12 hours and calls acme.sh --renew. This can fail if:
- Port 80 is no longer accessible from the internet
- The acme.sh installation was removed or corrupted
- DNS changed and no longer points to this server
Test renewal manually:
~/.acme.sh/acme.sh --renew -d example.com --forceCheck the error log for renewal messages:
grep -i "renew\|tls\|cert" /var/log/pshs/error.logRestart the server after fixing the underlying issue — the renewal thread will attempt renewal on the next 12-hour cycle.
If you've worked through this guide and still have issues:
-
Check the README — See
/Users/worajedt/PureBasic_Projects/PureSimpleHTTPServer/README.mdfor quick-start examples and flag reference -
Review other documentation — See the
/docs/user/directory for guides on:LOGGING.md— How to set up and monitor logs- Configuration flags and rewrite rules
-
Enable detailed logging — Start the server with
--log-level infoand--error-logto see what's happening:./PureSimpleHTTPServer \ --root /var/www \ --log /var/log/pshs/access.log \ --error-log /var/log/pshs/error.log \ --log-level info -
Check system logs — On systemd systems:
journalctl -u pshs -f
-
Report issues — If you believe you've found a bug:
- Note your command line and OS version
- Include relevant log excerpts
- Try to reproduce with the simplest possible setup
- Visit the project repository to file an issue