Self-Signed vs Purchased SSL Certificates for Intranet Web Services: A Developer’s Guide


2 views

When developing applications that consume internal web services, the requirement for HTTPS connections often creates a dilemma. Our team recently faced this exact scenario where our application needed to communicate with an intranet-hosted web service using HTTPS.

For internal services, we essentially have two options:

  1. Self-signed certificates: Generated internally without CA validation
  2. Purchased certificates: Issued by a trusted Certificate Authority (CA)

Here's how each approach looks in code when making HTTPS requests:


// Using self-signed certificate (Node.js example)
const https = require('https');
const fs = require('fs');

const options = {
  hostname: 'internal-service.company.local',
  port: 443,
  path: '/api',
  method: 'GET',
  ca: fs.readFileSync('self-signed-cert.pem'), // Must specify CA
  rejectUnauthorized: true // Important for security
};

const req = https.request(options, (res) => {
  // Handle response
});

// Using purchased certificate (standard HTTPS)
const https = require('https');

const options = {
  hostname: 'internal-service.company.local',
  port: 443,
  path: '/api',
  method: 'GET'
};

const req = https.request(options, (res) => {
  // Handle response
});

For self-signed certificates:

  • No cost involved
  • Requires manual certificate distribution to all clients
  • Needs additional code to handle certificate verification
  • Potential security risks if not implemented properly

For purchased certificates:

  • Minimal client-side configuration needed
  • Works seamlessly with most HTTP clients/libraries
  • Comes with automatic trust from all major operating systems
  • Involves annual costs

If you opt for self-signed certificates:


# Generate self-signed certificate (OpenSSL)
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes

For purchased certificates, consider these options:

  • Standard DV certificates (cheapest option)
  • Wildcard certificates if you have multiple subdomains
  • Private PKI if you have many internal services

Choose self-signed when:

  • You have complete control over all client machines
  • Certificate management infrastructure exists
  • Budget constraints prevent purchasing certificates

Choose purchased certificates when:

  • You need to support various client devices/platforms
  • Your development team prefers standard HTTPS behavior
  • You want to minimize maintenance overhead

Both approaches can be secure if implemented correctly. The main differences:

Factor Self-Signed Purchased
Encryption Strength Equal Equal
Trust Verification Manual Automatic
Revocation Handling Manual OCSP/CRL

For most internal web services that need to support various applications and developers, purchased SSL certificates provide the best balance between security and convenience. The cost is relatively low compared to the development time saved from not having to handle certificate distribution and verification in code.

However, if you have a controlled environment where you can manage certificate distribution effectively, self-signed certificates remain a viable option.


When developing applications that consume internal web services, the HTTPS requirement often comes up - even for services that never face the public internet. Here's why developers insist on HTTPS:

// Modern browsers block mixed content
fetch('http://internal-api.company.local/data') // Blocked in Chrome
  .then(response => response.json())
  .catch(err => console.error('Failed:', err));

// While HTTPS connections work normally
fetch('https://internal-api.company.local/data')
  .then(response => response.json());

For internal services, you essentially have three approaches:

Option Cost Setup Complexity Maintenance Browser Trust
Commercial SSL $50-$500/yr Low Annual renewal Full
Self-Signed Free Medium Manual updates Warnings
Internal CA Free High Centralized Full (when configured)

Self-signed certificates are perfectly viable for:

  • Development environments
  • Testing clusters
  • Temporary services
  • Prototyping phases

Here's how to generate one with OpenSSL:

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -subj "/CN=internal-service.local"

Purchased certificates become necessary when:

  • Multiple teams consume the API
  • You need to automate certificate distribution
  • Service availability is critical
  • You want to avoid certificate warnings

For enterprises, setting up an internal CA provides the best balance:

# Example of importing CA cert on Windows
Import-Certificate -FilePath "C:\certs\company-ca.crt" -CertStoreLocation Cert:\LocalMachine\Root

# On Linux (Debian/Ubuntu):
sudo cp company-ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates

When deciding, consider these technical factors:

  • Certificate revocation requirements
  • Support for modern cipher suites
  • SAN (Subject Alternative Name) requirements
  • Certificate transparency logging

For Node.js services, here's how to use a self-signed cert:

const https = require('https');
const fs = require('fs');

const options = {
  key: fs.readFileSync('key.pem'),
  cert: fs.readFileSync('cert.pem')
};

https.createServer(options, (req, res) => {
  res.writeHead(200);
  res.end('Secure internal service\n');
}).listen(8443);