Hardware FixRecommendedDevice not working? Your driver may be the problemCheck updates for common hardware issues.Fix DriversHalloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PC×
Skip to content
World desk12 min

How to Set Up WebSocket Connections Behind Nginx on a VPS

A complete guide to running WebSockets behind Nginx on a VPS, including a safe configuration, wss:// TLS setup, timeout tuning, deployment steps, and handshake troubleshooting.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Run the WebSocket application on a private listener such as 127.0.0.1:8080, then let Nginx publish the service on your hostname. Nginx terminates TLS, forwards an HTTP/1.1 upgrade request with the required Upgrade and Connection headers, and creates a tunnel after the application returns 101 Switching Protocols. Clients on an HTTPS site should connect with wss://example.com/ws/.

How the VPS arrangement works

A browser starts a WebSocket connection as an HTTP request containing an Upgrade: websocket header. Nginx receives that request on the public server, forwards it to the application, and switches into tunnel mode only when the upstream answers with HTTP status 101 Switching Protocols. From that point, WebSocket frames pass through the proxy rather than being handled as separate HTTP requests.

As an Amazon Associate I earn from qualifying purchases.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The application does not need to listen on the public interface. Binding it to 127.0.0.1 or another private interface keeps the backend port away from the internet while Nginx handles ports 80 and 443. A typical flow is:

  • Client: wss://example.com/ws/
  • Nginx TLS listener: TCP 443
  • Nginx upstream: http://127.0.0.1:8080
  • Application route: the WebSocket path configured by your framework

The public hostname, certificate name, Nginx location, and application route must agree. A mismatch in any one of them can produce a failed handshake even when the application itself is healthy.

#1 Best Overall
Sale
TOZO A1 Wireless Earbuds Bluetooth 5.3 Light Weight in Ear Headphones | IPX5 Waterproof,2 Mics for AI Calls,Immersive Premium Sound Bass Headset with Charging Case,32 EQ via App Black
  • [Ultra-Lightweight Ear Buds Designed for Small Ears] Each earbud weighs only 3.7g and features a compact, ergonomic in-ear design made especially for small ears. Secure, low-profile, and comfortable for workouts, all-day wear or overnight sleeping.The ultra-slim profile sits flush in your ear with no hard edges poking or rubbing, so you can even sleep on your side without discomfort.
  • [Immersive Stereo Sound with TOZO OrigX Technology] TOZO OrigX tuning delivers clear vocals, balanced mids, and natural stereo sound for music, podcasts, and videos.
  • [Long Battery Life for Daily Use] Get up to 7 hours of playtime on a single charge, with up to 32 hours total using the charging case—ideal for workdays, commuting, and extended listening sessions.
  • [Bluetooth 5.3 & Stable Connection] Bluetooth 5.3 provides fast pairing, stable wireless performance, and reduced dropouts as you move around home or office.
  • [Deep Bass with Clear Vocals] High-performance drivers produce punchy bass while keeping vocals clean and detailed for everyday listening.

Prerequisites before editing Nginx

Confirm the application listener

Know the exact address, port, and path on which the application accepts WebSockets. The example configuration assumes 127.0.0.1:8080 and a route beginning with /ws/; substitute your actual values. Test the process locally before adding the proxy. If it is bound only to a Unix socket, a TCP proxy_pass value will not work without adapting the upstream definition.

Point DNS and choose the public URL

Create an A or AAAA record for the hostname that clients will use, such as example.com. The certificate must cover that same hostname. Decide whether the application expects /ws/, /socket, or another path, including whether a trailing slash is significant.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Open only the public ports

Expose TCP 80 when you need HTTP redirect handling or certificate issuance, and TCP 443 for the encrypted service. Keep the application port private when Nginx and the application share the VPS. Do not open port 8080 in the VPS firewall unless a separate, trusted component genuinely needs direct access.

Reference Nginx configuration

Put the map directive in the global http context, not inside a server or location block. The WebSocket location belongs in the TLS-enabled server block.

# In the http{} block
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    location /ws/ {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 3600s;
    }
}

Replace the hostname, certificate paths, upstream address, and location path. Keep the certificate directives in the server block that listens on 443. If your distribution includes separate site files, enable the file in the normal way for that distribution before testing the effective configuration.

Why the WebSocket directives are required

Directive Purpose Configuration consequence
proxy_pass Selects the internal application listener. Match the scheme, address, port, and URI behavior to the backend route. A trailing slash changes how Nginx replaces the matched location prefix.
proxy_http_version 1.1 Uses HTTP/1.1 for the upstream handshake. Without it, older Nginx proxy defaults can prevent a successful upgrade.
proxy_set_header Upgrade $http_upgrade Passes the client’s requested protocol switch. Nginx does not forward this hop-by-hop header automatically; set it explicitly.
proxy_set_header Connection $connection_upgrade Tells the upstream whether to switch protocols. The map sends upgrade only when the request contains an Upgrade header and sends close otherwise.
proxy_set_header Host $host Preserves the public hostname. Applications can use the correct host for URL generation and origin checks.
X-Real-IP and X-Forwarded-For Carry the client address through the proxy. Configure the application framework to trust these headers only from your Nginx proxy.
X-Forwarded-Proto $scheme Reports whether the client used HTTP or HTTPS. Applications can avoid generating an http:// callback or redirect when the public request was encrypted.
proxy_read_timeout 3600s Controls how long Nginx waits between reads from the upstream. Quiet sockets can remain open for an hour in this example instead of using the documented 60-second default.

Why use a conditional map?

Upgrade and Connection are hop-by-hop headers. The map prevents ordinary HTTP requests that happen to share the location from receiving Connection: upgrade. If a location is exclusively for WebSockets, a fixed proxy_set_header Connection "upgrade"; can work, but the mapped form is safer when upgraded and ordinary requests may coexist.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
Sale
Smart Watch for Men Women Compatible with iPhone Samsung Android Phone 1.69 inch Full Touch Screen IP68 Waterproof Bluetooh Fitness Tracker Heart Rate/Sleep Monitor (Black)
  • 【IP68 Waterproof Multifunctinal Smart Watch】Torjalph fitness activity tracker smart watch is IP68 waterproof technology ,you can wear it when swimming,handwashing,it's rain-proof which means that you perform multiple exercise modes outside without worrying about sweat or rain corroding your fitness smart watch,and this watch equipped with a 230 mAh large capacity battery magnetic charging ,and this sports activity tracker watch can be used 5-7 days If fully charged.
  • 【Larger 1.83'' Full Screen Watch & Multi-dial Selection】1.83 inch full HD color touch screen smart watch for men / women provides excellent 240*284 resolution image quality ,This Bluetooth smart watch offers a better touch experience and remarkable immersion and ,more than 200 watch faces for you to choose from App"Da Fit ", you can change the dial style according to your mood to wear keeping the world on your wrist
  • 【Accurate Activity Tracker Smart Watch 】sports watch activity tracker uses sweat and dust resistant breathable silicone strap, our Fitness Tracker Smart Watch for Android iOS Phones supports 12 sports modes,walking,running,bicycle,swimming,badminton,basketball,football,rope skipping. This bluetooth calls smart watch for men women is lightweight and stylish, bringing more convenient and relaxing sports experience while also providing more protection.
  • 【Your 24 Hour Personal Daily Health Monitor】Fitness watch for women men full touch screen IP67 waterproof bluetooth smartwatch for Android iOS Phones with heart rate blood pressure monitor multifunction Andriod smart watch with steps counter sleep monitor sports fitness watch, monitoring blood oxygen saturation allows you to understand your physical condition in real time to track fitness progress ,to know your health status in time.
  • 【More Functions Bluetooth Call Smart Watch】This fitness activity smart watch full screen for iPhone and Android phones includes a bunch of new features including:The bluetooth smart watch can hang up the phone, receive and display WhatsAPP /Text /Facebook /Twitter /Messenger reminder.Support sedentary reminder, alarm clock, stopwatch, timer,weather information,music control, remote camera control compatible with Android 5.0 and above or iOS 9.0 and above smartphones.

Mapped versus fixed connection headers

Use the mapped form when a location might receive health checks, browser preflight requests, or ordinary HTTP traffic. A request without an Upgrade header receives Connection: close, while a genuine upgrade receives Connection: upgrade. A fixed value is simpler for a location that is strictly dedicated to WebSockets, but it can incorrectly label non-WebSocket requests if the location later gains another purpose. Keep the map at http{} scope so every relevant server block can use the same variable.

Deploy the configuration safely

  1. Verify the backend. Confirm that the process is running, listening on the intended private address and port, and serving the documented WebSocket path.
  2. Add the map and server blocks. Place the map in http{}; place the /ws/ location in the 443 server block, not only in the port-80 redirect block.
  3. Check the effective configuration. Run your distribution’s Nginx syntax test before reloading. On standard Nginx installations, that is sudo nginx -t. Resolve every reported error first.
  4. Reload Nginx. Use the service manager supplied by your distribution, commonly sudo systemctl reload nginx, so existing connections are not needlessly terminated.
  5. Test the public endpoint. Use a WebSocket-capable client against ws:// for an unencrypted endpoint or wss:// for the TLS endpoint. A successful handshake returns HTTP 101.
  6. Observe logs during the test. Keep the Nginx access and error logs, the application log, and any VPS firewall log visible while making a connection. The first failing hop is usually apparent from those records.

Reload only after the syntax check succeeds. A reload applies the new workers while allowing existing workers to finish their current work; this is preferable to an unnecessary stop-and-start cycle for a service carrying long-lived sockets. Confirm the active configuration, rather than assuming that an edited file is the file Nginx loaded, especially when a distribution uses enabled-site links or multiple include files.

Getting URI and trailing-slash behavior right

Nginx location matching and proxy_pass URI syntax determine the path sent upstream. If the client requests /ws/chat and the location is location /ws/, compare the backend’s expected route with the exact path produced by your chosen proxy_pass form. A pass value with a URI component can replace the matched location prefix; a pass value without one preserves more of the original request URI.

Do not assume that /ws and /ws/ are interchangeable. Framework routers, authentication middleware, and origin checks may treat them as different routes. Test the exact path your client uses, including query parameters if your application relies on them.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For example, a backend that expects /chat may require a location and pass form that removes the public /ws/ prefix, whereas a backend expecting /ws/chat may need the original prefix preserved. Make this choice deliberately and document it with the application route. A 404 at handshake time is often a URI transformation problem, not a WebSocket protocol problem.

Keeping long-lived sockets open

Understand the read timeout

Nginx’s documented proxy read timeout is 60 seconds by default. It measures the interval between reads from the upstream, not the total lifetime of the connection. A connection that sends no data during that interval can be closed even if both endpoints consider it healthy. Set a longer value, such as 3600s, when quiet connections are expected.

Rank #3
New Bee Guitar Cable 10ft Electric Instrument Bass AMP Cord
  • [Low Noise High Fidelity] New bee guitar cord with 22AWG oxygen-free-copper center conductors provides enhanced signal transfer, the PVC insulation material and the high-density stranded copper double shield provide noise rejection for quiet operation
  • [Ideal for Choice] New bee 1/4 straight and right angle metal connectors, ensures a secure connection in any instrument, pedal, or amp jack. L shape great fro on stage guitar stands
  • [Wide Compatible] Suitable for mixer, power amplifier, microphone, effector, decoder, equalizer, electoronic organ, electric guitar, electric bass and other electronic equipments. Widely used in the installation of smart home, karaoke speaker, professional stage audio, etc
  • [Easy Disassemble] Making incidental repairs quick and easy! Very nice, flexible cable
  • [Dont Hesite to Order] 24 hours customer services and professional technology team are standing by

Prefer application heartbeats

A long proxy timeout is not a substitute for liveness detection. Configure the WebSocket server to send periodic ping frames and to answer pong frames according to its framework’s API. Heartbeats keep traffic flowing, reveal dead clients, and allow the application to release stale sessions. Choose an interval comfortably shorter than the proxy timeout and any intervening load balancer or firewall timeout.

Coordinate every intermediary

If traffic passes through another proxy, firewall, or load balancer before reaching the VPS, its idle policy can close the connection first. The Nginx value only governs Nginx’s upstream read interval; it cannot override a shorter timeout elsewhere.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Remember that the timeout is about upstream reads, so a busy socket can stay open indefinitely without reaching the idle limit. Conversely, a client that is connected but silent can be dropped even when the TCP connection initially succeeded. Test both active messaging and a deliberately quiet connection to validate the selected value.

TLS and the wss:// endpoint

When the page itself is delivered over HTTPS, browsers generally block an insecure ws:// connection as mixed content. Use wss://example.com/ws/, terminate TLS in the 443 server block, and proxy the decrypted connection to the private HTTP listener. The certificate hostname must match the name in the client URL.

Port 80 can redirect ordinary HTTP requests to HTTPS, but the WebSocket location must also exist in the 443 server block. A configuration that works on an unencrypted test port can still fail over TLS if the secure server selects a different configuration or lacks the location entirely.

The exact certificate issuer, renewal method, and file paths depend on the Linux distribution and certificate tooling. Keep those certificate-management steps separate from the WebSocket proxy directives, and verify that renewal leaves the Nginx process able to read the updated files.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #4
BSIMB 15.6" Digital Family Calendar & Chore Chart, No Subscription Fees
  • Digital Family Calendar: BSIMB digital calendar wall touch screen puts an end to your chaotic life. Designed for busy families, the digital calendar keeps you organised and in step with your family. Assign different colours and tasks to each family member to make family scheduling easier and more intuitive.
  • Easy Setup and Auto-Sync: Plug in, connect to WLAN and auto-syn your electric calendar in minutes. Digital wall calendar compatible with Google calendar, iCloud calendar, Outlook calendar, Cozi calendar and Yahoo calendar. Add events directly on the device or through the ecalendar app. Electronic calendar stays current whether you're at work or traveling—no manual updates needed.
  • All-In-One Home Assistant: Smart calendar builds habits and encourage independence with personalised chores. Display daily meal plan to reduce the daily ‘What's for dinner?’ stress. To-do lists keep track of everything you want. Turning chores into valuable achievements with stars and rewards, making life easier and more enjoyable.
  • Manage Anytime Anywhere: BSIMB electronic calendar for family stay connected with the powerful ecalendar app. Access and manage your digital wall calendar anytime, anywhere with free features like stars & rewards, photo screensaver, chore charts, meals plans, to-do lists etc. Electronic planner paid features like Magic Import tailor advanced tools for users with special needs.
  • Stay in Touch with Loved Ones: Share photos or videos from your phone to electronic wall calendar with app, instantly update your life moment, and keep in touch with your family, especially those who are far away; you can also surprise your smart calendar digital wall by sending him a wish card; it's also great for keeping tech-illiterate elders in touch with the youngsters.

TLS termination does not change the backend scheme in the example: the browser uses wss://, Nginx decrypts on 443, and Nginx connects to the local service with http://127.0.0.1:8080. The X-Forwarded-Proto header communicates the original secure scheme so the application can make correct URL and redirect decisions.

Test the handshake and read the result

What success looks like

The client sends an HTTP upgrade request, Nginx forwards it with HTTP/1.1 and the hop-by-hop headers, and the backend responds with 101 Switching Protocols. After that response, the connection is a bidirectional WebSocket tunnel. Application messages, ping/pong frames, and close frames should appear in the application’s normal protocol logs rather than as new HTTP requests.

Test from the same network conditions your users will have when possible. A local test to 127.0.0.1 can prove that the application works, but only a public test validates DNS, certificate selection, firewall rules, the 443 server block, and the complete proxy path. Include authentication cookies, query strings, and origin headers in the test if the application requires them.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use the logs to locate the failing hop

  • An Nginx access entry with status 101 confirms that the proxy completed the handshake.
  • A 404 usually means the client path, Nginx location, and backend route do not line up.
  • A 400 often points to an invalid handshake or missing/incorrect upgrade headers; verify what the client actually sent.
  • A 502 or 504 generally means Nginx could not reach a healthy upstream; inspect the process, address, port, local firewall, and proxy scheme.

These status codes are troubleshooting starting points, not proof of one cause. Confirm each interpretation against both Nginx’s error log and the application log.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting by symptom

Symptom Checks Likely correction
Immediate close or HTTP 400 Inspect the client handshake and the location’s proxy_http_version, Upgrade, and Connection settings. Use HTTP/1.1 upstream and pass the upgrade headers explicitly. Confirm the client is actually requesting an upgrade.
HTTP 502 Bad Gateway Check that the backend process is running, bound to the address in proxy_pass, reachable locally, and not blocked by a local firewall. Correct the upstream address, port, or scheme, then reload after the configuration test passes.
HTTP 404 during the handshake Compare the browser URL, Nginx location, backend route, and trailing slashes. Make the three paths consistent and retest the exact URL.
HTTP 504 or a timeout Inspect upstream reachability and the interval between backend reads. Repair the unhealthy backend and set an appropriate proxy_read_timeout; add application heartbeats for quiet sockets.
Disconnect after roughly one minute Look for a 60-second idle gap in the logs and check whether the application sends ping or other traffic. Raise the read timeout and implement periodic ping/pong traffic.
Works over HTTP but not HTTPS Verify the certificate hostname, browser mixed-content rules, wss:// URL, and the location in the 443 server block. Serve the matching certificate, use the secure URL, and place the WebSocket proxy settings in the TLS server.
Wrong client IP or generated scheme Inspect the forwarded headers and the framework’s trusted-proxy configuration. Preserve the forwarded headers in Nginx and trust them only from the proxy that you control.

Security and operational checks

  • Bind the application to localhost or a private interface unless direct external access is an intentional requirement.
  • Allow TCP 80 and 443 through the VPS firewall only when those services are needed; keep the backend port closed publicly.
  • Use the public hostname in the certificate, client URL, and Nginx server_name.
  • Restrict the WebSocket location to the intended path instead of proxying every URI to the application by accident.
  • Preserve Host, client-address, and scheme headers only when the application is configured to trust them from Nginx.
  • Watch connection counts, error logs, and application resource use. WebSockets consume an open process connection for their entire lifetime, so backend limits and graceful shutdown behavior matter even when the proxy configuration is correct.

Do not treat a successful TCP connection as proof that the service is ready. The backend must complete the protocol handshake, and the application must authenticate and authorize the resulting session according to its own rules. Nginx forwards the request; it does not replace application-level origin checks, session validation, or resource limits.

Production checklist

  1. The application listens on the expected private address and WebSocket route.
  2. DNS resolves the public hostname to the VPS.
  3. The certificate covers that hostname and is readable by Nginx.
  4. TCP 80 handles the intended redirect or certificate workflow, and TCP 443 serves the secure endpoint.
  5. The map is in http{}, while the WebSocket location is in the 443 server block.
  6. The upstream uses HTTP/1.1 and receives explicit Upgrade and conditional Connection headers.
  7. Forwarded headers match the framework’s trusted-proxy settings.
  8. The proxy read timeout and application heartbeat interval suit the expected idle period.
  9. nginx -t passes before every reload.
  10. A real client receives HTTP 101, and the logs remain clean during messages, ping/pong frames, and a normal close.

Frequently Asked Questions

What exactly must Nginx send for a WebSocket handshake?

The upstream request should use HTTP/1.1 and explicitly include Upgrade $http_upgrade plus a matching Connection value. Nginx does not forward these hop-by-hop headers automatically. The backend must then return HTTP 101 Switching Protocols.

Can I hard-code Connection: upgrade?

Yes, when the location is exclusively for WebSockets. The conditional map is safer for a shared location because ordinary requests receive Connection: close instead of being labeled as upgrades.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why does the connection close after about 60 seconds?

The documented default proxy_read_timeout is 60 seconds between upstream reads. Increase it, for example to 3600s, and configure application ping/pong heartbeats so quiet connections still generate traffic.

What does a 502 mean in this setup?

It generally means Nginx cannot reach a healthy upstream. Check that the process is running, the address and port match proxy_pass, the local firewall allows the connection, and the proxy scheme is correct.

Why do I receive 404 during the handshake?

Compare the browser’s exact URL with the Nginx location and the application route. Check /ws versus /ws/, query strings, and whether the proxy_pass URI form replaces or preserves the matched prefix.

Do I need to expose port 8080 publicly?

No. When Nginx and the application share the VPS, bind the service to localhost or a private interface and expose only the public ports required for the service, normally TCP 443 and optionally TCP 80 for redirects or certificate workflows.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How do I run secure WebSockets on a VPS?

Use a certificate covering the public hostname, place the WebSocket location in the listen 443 ssl server block, and have the browser connect to wss://. Nginx terminates TLS and can proxy the decrypted request to the private HTTP listener.

What does HTTP 101 prove?

It confirms that the upgrade handshake completed through Nginx and the backend. It does not by itself prove that application authentication, authorization, heartbeat handling, or message processing is configured correctly.

Why are the client IP and scheme wrong in my application?

Ensure Nginx sends Host, X-Real-IP, X-Forwarded-For, and X-Forwarded-Proto. Then configure the framework to trust those values only from the Nginx proxy you control.

The Bottom Line

Keep the WebSocket service private, publish it through the TLS-enabled Nginx server, and use HTTP/1.1 with explicit upgrade headers. Put the conditional map in http{}, match the URI exactly, raise the 60-second idle timeout when needed, and verify every change with nginx -t, logs, and a real client that receives 101 Switching Protocols.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.