██ Run Your Own Web Server Session: S7 2026-09-19 1 / 23 ██ A Client Asks, A Server Answers A client is a program that sends a request. A server is a program that waits for
requests and answers them. client -- request --> server
client <-- response -- server
Your browser is a web client. Curl is a client too.
Here, "server" means the running program, not the whole computer. 2 / 23 ██ HTTP Defines The Exchange A protocol defines how programs exchange messages. HTTP defines web requests and
responses. • The client requests a path, such as /index.html.
• The server answers with a status, headers, and usually a body such as HTML. The browser displays the page. Curl prints the response in your terminal. HTTPS protects this exchange using TLS, which encrypts the connection and verifies the server's identity. 3 / 23 ██ Caddy Already Serves Your Site Caddy is the web-server program already serving your site on the classroom machine.
Today you will run your own Caddy process to learn to start it, request a page, stop it, and recover it without affecting others. We will connect to it locally first, then from your laptop browser. 4 / 23 ██ Localhost Keeps The Connection Local localhost targets the host where the client process runs, using a loopback address:
127.0.0.1 (IPv4) or ::1 (IPv6). The traffic stays inside that host's network stack.
Curl launched in your SSH session runs on the classroom server. A request to localhost therefore reaches a service on that server, not on your laptop. We will
use 127.0.0.1 explicitly.
We will first ask your server for a page from that same machine. 5 / 23 ██ A Port Selects A Service An IP address identifies the network destination. A port selects a listening service
at that address. • The server listens on an address and port.
• The client connects to that address and port.
Example: two services on the same host: 127.0.0.1:22 -> SSH server
127.0.0.1:8000 -> HTTP server
HTTP uses port 80 by default. Your server will use its own assigned port:
PORT="$((10000 + $(id -u)))"
How does this calculate your port? 6 / 23 ██ Start Your Server caddy file-server --listen :$PORT --root ~/public_html
--access-log
• --listen sets the port your server accepts connections on.
• --root sets the folder containing the files to serve.
• --access-log records requests.
7 / 23 ██ Request A Page With Curl Open a second SSH connection: PORT="$((10000 + $(id -u)))"
curl -i --max-time 10 "http://127.0.0.1:$PORT/"
-i displays the status line and headers before the page's HTML.
Curl is the client. Your Caddy process is the server. Both are running on the
classroom machine. In the server terminal, find the access-log record for this request: method GET, URI
/, and its status. You can now see both sides of the exchange.
8 / 23 ██ Reach Your Server Through A Reverse Proxy The classroom firewall blocks direct external access to your port. How can your laptop browser reach your server? For your personal service address, shared Caddy is already configured to pass requests to your assigned port and return the responses: browser -> shared Caddy -> personal Caddy
browser <- shared Caddy <- personal Caddy
Shared Caddy is a reverse proxy: a server to the browser and a client to personal
Caddy. Personal Caddy is the backend, the server answering the forwarded request.
Same software, two processes with different roles. 9 / 23 ██ Open Your Site From Your Laptop Open your service homepage (https://your-handle.lf2607.kolamayermakers.org/) in the
laptop browser, replacing your-handle with your username.
Look for the same page you just fetched with curl. Watch for the browser's request in your personal Caddy terminal. Shared Caddy handles the browser's HTTPS connection. Personal Caddy uses local HTTP. Keep the command as given, without --domain; no shared configuration changes are
needed. 10 / 23 ██ Proxies Can Represent Clients Or Servers A proxy is an intermediary: it forwards requests and sends responses back.
A forward proxy represents clients when requesting resources from destination
servers. clients -> forward proxy -> destination servers
A reverse proxy represents servers, forwarding incoming requests to backends.
clients -> reverse proxy -> backend servers
The distinction is which side the proxy represents, not the direction of HTTP. Access filtering and load distribution are examples of proxy uses; our shared Caddy forwards requests to your server. 11 / 23 ██ Follow A Visitor's Request In The Logs Ask a peer to open your service homepage, then request /missing.html on the same
hostname. Watch the first terminal. Find the time or timestamp, request.method, request.uri,
and status in the structured access logs.
What client address appears in the log? Can you explain why, even when the request comes from your peer's browser? 12 / 23 ██ Identify The Process Serving Your Page In the second terminal: ps -u "$USER" -o pid,comm,args
Which row is your server? Find its PID, the process ID, and the command that started
it. What tells you which port and files this process serves? 13 / 23 ██ Match The Process To Its Listening Port ss -ltnp "sport = :$PORT"
• -l: listening sockets.
• -t: TCP sockets.
• -n: numeric addresses and ports.
• -p: process information.
The filter selects your port. Does the PID match the Caddy process you found with ps?
A listening socket is the endpoint where the server waits for connections.
14 / 23 ██ HTTP Messages Need Line Endings The names come from typewriters and printing terminals. Starting a new line involved two movements: • \r: carriage return (CR), return to the start of the line.
• \n: line feed (LF), advance the paper by one line.
Text formats kept different conventions: • Unix text files use \n.
• Windows text files traditionally use \r\n.
• HTTP/1.1 uses \r\n to end request and header lines.
A blank line after the last header gives \r\n\r\n: the headers are finished.
15 / 23 ██ Send An HTTP Request By Hand In the second terminal, connect to your server: nc -C -N 127.0.0.1 $PORT
Type this request, replacing 11234 with your numeric port:
GET / HTTP/1.1
Host: localhost:11234
Press Enter on a blank line to end the headers, then Ctrl-D with no pending input.
• GET / HTTP/1.1: method, requested path, protocol version.
• Host: the requested hostname and port.
• -C sends HTTP's CRLF (\r\n) line endings when you press Enter.
• -N finishes sending on end-of-input, while still receiving the reply.
Find your request in Caddy's log. Which parts did curl previously write for you? 16 / 23 ██ Repeat The Request With A Script Save as ~/scripts/http-request.sh:
#!/bin/bash
PORT=$((10000 + $(id -u)))
printf '%s\r\n' \
'GET / HTTP/1.1' \
"Host: localhost:$PORT" \
'' |
timeout 5s nc -N -w 3 127.0.0.1 "$PORT"
Run bash ~/scripts/http-request.sh.
printf supplies the lines you typed, including the final blank line. When it
finishes, the pipe supplies EOF instead of Ctrl-D.
17 / 23 ██ Change The Path, Observe The Response In your script, change only GET / HTTP/1.1 to GET /missing.html HTTP/1.1, then run
it again. Predict the status. Compare the response with the matching entry in Caddy's access log. Now request the same path with curl: curl -i http://127.0.0.1:$PORT/missing.html
What is the same? What did curl save you from writing? 18 / 23 ██ What If Two Servers Use The Same Port? Keep your server running. Try starting another one from the second terminal: caddy file-server --listen :$PORT --root ~/public_html
--access-log
Why did this launch fail? Use ps and ss to identify the process already listening.
Does the original server still answer curl? Do not change the port or stop the existing process to hide the error. 19 / 23 ██ What If The Server Has No Files? Stop your server with Ctrl-C. In that terminal, serve a new empty practice
directory: practice_root=$(mktemp -d) &&
caddy file-server --listen :$PORT --root "$practice_root"
--access-log
Request / locally and through your service address. Is the process running? Is the
port listening? What do the response and log tell you? The practice directory is public through the proxy; leave it empty. Your real site files are unchanged. Stop this server, restart the original command with --root ~/public_html, and verify
the page is back. 20 / 23 ██ What Happens When Your Server Stops? If you stop your Caddy process, which of these three URLs will still respond? Why? curl -I http://127.0.0.1:$PORT/
curl -I https://$USER.lf2607.kolamayermakers.org/
curl -I https://lf2607.kolamayermakers.org/~$USER/
Share your predictions, then press Ctrl-C in the terminal running your Caddy
process. Run these requests in the second SSH terminal. Which requests still get a response? Who sends each response? Start Caddy again with the same command, then repeat the three requests. What changed? 21 / 23 ██ Explain What Runs And What Responds Explain how you found your server's process and listening socket, what you sent with netcat, and how you distinguished the three incidents. Confirm the service page works again, then stop your server with Ctrl-C. The static
site stays available. This process is not supervised. Keeping it running after logout is the next session's problem. 22 / 23 ██ Next: Keep It Running After Logout S8: 2026-09-26. Make Caddy start automatically, keep running after logout, and restart if it crashes. Use the self-study route (/docs/sessions/S07/self-study.md/) for complete examples
and troubleshooting. Use guide if you need help between sessions.
23 / 23