Oracle Solaris 11.4 on OCI Apache HTTP Server, Solaris PF Firewall and Let's Encrypt HTTPS

 

Purpose and scope

This runbook provides a repeatable procedure for deploying an Oracle Solaris 11.4 x86 compute instance on Oracle Cloud Infrastructure, configuring the system timezone, installing and enabling Apache HTTP Server 2.4, opening TCP ports 80 and 443 through both OCI network controls and the Solaris PF firewall, publishing a static webpage, and obtaining a browser-trusted TLS certificate from Let's Encrypt with acme.sh.

Intended audience

·         OCI administrators and cloud engineers.

·         Solaris administrators who need a small public web server.

·         Technical demo and lab environments where a reproducible Solaris 11.4 configuration is required.

Primary implementation choices

Layer

Choice

Reason

Compute

OCI Compute + Oracle Solaris 11.4 x86

Native OCI deployment target for this runbook.

Package management

IPS / pkg

Native Solaris software lifecycle tooling.

Service management

SMF / svcadm / svcs

Native Solaris service control and persistence.

Web server

Apache HTTP Server 2.4

Delivered by Solaris IPS package web/server/apache-24.

Host firewall

Solaris PF

Solaris 11.4 network firewall framework.

TLS certificate

Let's Encrypt via acme.sh

Shell-based ACME client with webroot issuance and automated renewals.

ACME challenge

HTTP-01

Works with an already-running Apache site and requires TCP/80 reachability.

Conventions and variables

Replace the following placeholders before running commands:

Variable

Example

Meaning

<PUBLIC_IP>

203.0.113.10

OCI public IPv4 address.

<PRIVATE_IP>

172.16.10.186

Solaris VNIC private address.

<ADMIN_PUBLIC_IP>

198.51.100.25/32

Your workstation public IPv4 CIDR.

<FQDN>

solaris.example.com

DNS name used for HTTPS.

<EMAIL>

admin@example.com

ACME registration/contact email.

Important: For the HTTPS procedure, use an FQDN that resolves publicly to the OCI public IP. Prefer an OCI Reserved Public IP so the DNS A record remains stable.


4 Prerequisites

Before starting, confirm the following:

• An OCI tenancy and compartment where you can create or administer compute, VCN, subnet, route, public-IP and NSG resources.

• An SSH key pair and administrative access to the Solaris instance.

• A public DNS zone or DNS provider account for the FQDN used by Let's Encrypt.

• A stable public IPv4 address for the final DNS record; an OCI Reserved Public IP is preferred for a persistent endpoint.

• Outbound Internet access from Solaris so IPS, acme.sh and the ACME service can be reached.

• A maintenance window or active fallback SSH session while changing the Solaris PF rules.

Target architecture

Internet
                               |
                      DNS A record: <FQDN>
                               |
                               v
                       OCI Public IPv4
                               |
                        Internet Gateway
                               |
                         Public Subnet
                               |
                         OCI NSG / SL
                 +-------------+-------------+
                 |             |             |
               TCP/22        TCP/80        TCP/443
             Admin /32       Public         Public
                 |             |             |
                 +-------------+-------------+
                               |
                         VNIC / net0
                         <PRIVATE_IP>
                               |
                      Solaris PF Firewall
                 +-------------+-------------+
                 |             |             |
               TCP/22        TCP/80        TCP/443
                               |
                               v
                        Apache HTTP 2.4
                     HTTP/80     HTTPS/443
                               |
                      /var/apache2/2.4/htdocs


Traffic path

1. The client resolves <FQDN> to the OCI public IPv4 address.

2. The OCI Internet Gateway and subnet route table provide Internet routing.

3. The NSG or applicable Security List permits inbound TCP/80 and TCP/443.

4. OCI maps the public IPv4 address to the instance private IP. Solaris normally sees only the private address on net0.

5. Solaris PF evaluates the inbound packet and permits the configured web ports.

6. Apache accepts the request and serves content from the configured DocumentRoot.

Required OCI network objects

·         VCN.

·         Public subnet.

·         Internet Gateway attached to the VCN.

·         Route rule 0.0.0.0/0 to the Internet Gateway.

·         Public IPv4 address on the Solaris VNIC, preferably Reserved for DNS use.

·         NSG or Security List rules allowing TCP/80 and TCP/443. SSH should be limited to the administrator's public /32 where practical.

Deploy Oracle Solaris 11.4 on OCI

Create or select the VCN

1. Open OCI Console and select the target compartment.

2. Open Networking > Virtual Cloud Networks.

3. Create or select a VCN.

4. Create a public subnet for the Solaris instance.

5. Create or confirm an Internet Gateway for the VCN.

6. In the subnet route table, add 0.0.0.0/0 with the Internet Gateway as the target.

Create the NSG

Create an NSG such as solaris-web-nsg and add stateful ingress rules:

Source

Protocol

Destination port

Use

<ADMIN_PUBLIC_IP>/32

TCP

22

SSH administration.

0.0.0.0/0

TCP

80

HTTP and Let's Encrypt HTTP-01.

0.0.0.0/0

TCP

443

HTTPS.

 For a private lab, TCP/80 and TCP/443 can also be restricted to known source ranges until ACME validation is required

Launch the Solaris instance

1. Open Compute > Instances > Create instance.

2. Select an Oracle Solaris 11.4 x86 image available to your tenancy. Search in marketplace

3. Choose a compatible compute shape.

4. Select the public subnet and attach solaris-web-nsg.

5. Assign a public IPv4 address.

6. Add your SSH public key.

7. Create the instance and wait until its lifecycle state is Running.

8. Record the public IP and private IP.




Connect

ssh -i <PRIVATE_KEY> opc@<PUBLIC_IP>
sudo -i

Verify identity and platform:

whoami
hostname
cat /etc/release
uname -a



Configure timezone to Asia/Kolkata

Check the current timezone

date
nlsadm get-timezone

A new instance can report UTC.



Confirm the target zone exists

nlsadm list-timezone | grep Kolkata

Expected match:

Asia/Kolkata


If pkg search is degraded

During the validated session, nlsadm produced a package-search performance warning. Rebuild the IPS search index if this occurs:

pkg rebuild-index

Then rerun the timezone list command.

4.4 Set the timezone

nlsadm set-timezone Asia/Kolkata

Expected command result includes a successful SMF property update.

Verify

date
nlsadm get-timezone
svcprop -p timezone/localtime svc:/system/timezone:default

Expected values:

<current date/time> IST
timezone=Asia/Kolkata
Asia/Kolkata

Solaris-specific note: Use svc:/system/timezone:default when querying timezone/localtime. Querying svc:/system/timezone without the :default instance can fail with a property-group error.




Verify or install Apache HTTP Server 2.4

Check the IPS publisher

pkg publisher

On the validated OCI image, the Solaris publisher was online and pointed to the OCI Solaris support repository.

Check whether Apache is installed

pkg list web/server/apache-24

If the package is installed, the IFO column includes i. 



Install Apache when missing

pkg install -nv web/server/apache-24
pkg install web/server/apache-24

The first command previews the IPS transaction; the second performs the installation.

Check Apache version and syntax

/usr/apache2/2.4/bin/apachectl -v
/usr/apache2/2.4/bin/apachectl configtest

Required syntax result:

Syntax OK




Check the service state

svcs -a | grep apache

A fresh system can show:

disabled   ...   svc:/network/http:apache24

Enable Apache through SMF

svcadm enable svc:/network/http:apache24
svcs svc:/network/http:apache24
svcs -xv svc:/network/http:apache24

The service should become online.



Confirm the document root

grep -n "^DocumentRoot" /etc/apache2/2.4/httpd.conf
ls -la /var/apache2/2.4/htdocs

For the standard Solaris Apache 2.4 package, the working runbook uses:

/var/apache2/2.4/htdocs



Publish a simple webpage

Back up the existing page

cd /var/apache2/2.4/htdocs
[ -f index.html ] && cp -p index.html index.html.pre-runbook



Create the page

cat > /var/apache2/2.4/htdocs/index.html <<EOF
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Oracle Solaris on OCI</title>
  <style>
    body { font-family: Arial, Helvetica, sans-serif;
           background: #f4f4f4; margin: 0; padding: 0; }
    .container { max-width: 800px; margin: 80px auto;
                 background: #fff; padding: 40px; border-radius: 10px;
                 box-shadow: 0 4px 15px rgba(0,0,0,0.15); }
    .server-info { margin-top: 25px; padding: 20px;
                   background: #f1f1f1; border-radius: 6px; }
  </style>
</head>
<body>
<div class="container">
  <h1>Oracle Solaris 11.4 on OCI</h1>
  <p>Welcome to my Oracle Solaris web server running on Oracle Cloud Infrastructure.</p>
  <div class="server-info">
    <h2>Server Information</h2>
    <p><strong>Cloud:</strong> Oracle Cloud Infrastructure</p>
    <p><strong>Operating System:</strong> Oracle Solaris 11.4</p>
    <p><strong>Web Server:</strong> Apache HTTP Server 2.4</p>
    <p><strong>Hostname:</strong> $(hostname)</p>
    <p><strong>Timezone:</strong> Asia/Kolkata</p>
    <p><strong>Generated:</strong> $(date)</p>
  </div>
</div>
</body>
</html>
EOF

Because EOF is unquoted, the hostname and current date are expanded when the file is created.

Test locally

curl -I http://localhost/
curl http://localhost/

Expected status:

HTTP/1.1 200 OK




Identify the VNIC address

ipadm show-addr -p -o ADDROBJ,ADDR

Example from the validated session:

lo0/v4:127.0.0.1/8

net0/v4:172.16.10.43/24

lo0/v6:\:\:1/128

Test using the private IP:

curl -I http://<PRIVATE_IP>/



Verify port 80 is listening

netstat -an -P tcp | grep '\.80 '
ps -ef | grep '[h]ttpd'



A listener shown as *.80 confirms Apache is accepting TCP/80 on the host

Configure the Solaris PF firewall for 80 and 443

Oracle Solaris 11.4 uses PF as the host firewall. The OCI Solaris image validated in this session had the firewall service online and used a restrictive SSH-only rules file. HTTP failed externally until an explicit TCP/80 rule was added.

Inspect firewall state

svcs -xv svc:/network/firewall:default
svcs -a | grep firewall



If the service is online, inspect its active rules.

Inspect active rules

pfctl -sr
pfctl -a '*' -sr



The validated SSH-only policy contained the following effective pattern:

block return all
pass in proto tcp from any to any port = 22 flags S/SA
pass out all flags S/SA

With no TCP/80 or TCP/443 pass rule, inbound web traffic is blocked at the Solaris host.

Identify the persistent rules file

svcprop firewall:default | grep ^firewall

In the validated session:

firewall/rules astring /etc/firewall/pf_ssh_only.conf

Create a custom rules file

cp -p /etc/firewall/pf_ssh_only.conf /etc/firewall/pf_web.conf
ls -l /etc/firewall/pf_ssh_only.conf /etc/firewall/pf_web.conf
ls -l/v /etc/firewall/pf_web.conf




Clear the inherited readonly attribute if present

Inspect:

ls -l/v /etc/firewall/pf_web.conf

If the attribute list contains readonly, clear only that attribute on the custom copy:

chmod S-cR /etc/firewall/pf_web.conf
chmod 644 /etc/firewall/pf_web.conf
ls -l/v /etc/firewall/pf_web.conf

Verify that the output now contains noreadonly. Leave /etc/firewall/pf_ssh_only.conf unchanged.

If you deliberately need to clear every special attribute on the copy, Solaris also supports chmod S-a file, but the targeted readonly clear is preferred here.


Allow HTTP and HTTPS in PF

Edit the custom policy
vi /etc/firewall/pf_web.conf

Locate:

# accept incoming SSH connections
pass in proto tcp to any port 22

Immediately below it add:

# Allow HTTP
pass in inet proto tcp from any to any port 80

# Allow HTTPS
pass in inet proto tcp from any to any port 443

Validate before loading

pfctl -nf /etc/firewall/pf_web.conf

No output indicates that the syntax check succeeded. Keep the current SSH session open while changing firewall rules.

Load the rules into the running kernel

pfctl -f /etc/firewall/pf_web.conf
pfctl -sr | egrep 'port = (22|80|443)'

Expected relevant rules:

pass in proto tcp from any to any port = 22 flags S/SA
pass in inet proto tcp from any to any port = 80 flags S/SA
pass in inet proto tcp from any to any port = 443 flags S/SA



Make the custom rules file persistent

svccfg -s svc:/network/firewall:default \
  setprop firewall/rules = astring: /etc/firewall/pf_web.conf

svcadm refresh svc:/network/firewall:default
svcadm restart svc:/network/firewall:default

Verify persistence and service health:

svcprop -p firewall/rules svc:/network/firewall:default
svcs -xv svc:/network/firewall:default
pfctl -sr | egrep 'port = (22|80|443)'



Expected persistent path:

/etc/firewall/pf_web.conf


Validate HTTP from outside OCI

Check OCI controls

Check

Required state

VNIC

Public IPv4 address assigned.

Subnet

Public subnet.

Route

0.0.0.0/0 points to the Internet Gateway.

Internet Gateway

Enabled.

NSG/Security List

TCP/80 allowed from the required source.

Solaris PF

TCP/80 pass rule loaded.

Apache

Port 80 listening and HTTP 200 locally.


Test from Windows

Test-NetConnection <PUBLIC_IP> -Port 80
curl.exe -v http://<PUBLIC_IP>/





The validated deployment successfully displayed the page in a browser after the PF TCP/80 rule was added.

Packet-level isolation when needed

If local HTTP works but the public IP still fails, run Solaris packet capture while testing from an external client:

snoop -d net0 port 80

If no inbound SYN reaches net0, inspect OCI routing, the public IP association, NSG membership, and Security Lists. If packets reach net0 but no response is sent, inspect PF and Apache.

Prepare DNS and the public IP for HTTPS

Prefer a Reserved Public IP

For a long-lived TLS endpoint, assign a Reserved Public IPv4 address to the Solaris VNIC. This avoids an FQDN pointing to a different address after an instance or VNIC lifecycle change.

Create a DNS A record

At your authoritative DNS provider create:

Type

Name

Value

A

solaris (or chosen host label)

<PUBLIC_IP>

 

The resulting FQDN might be:

solaris.example.com

Verify public DNS before ACME

getent hosts <FQDN>
curl -I http://<FQDN>/

The name must resolve to the OCI public IP and HTTP must be reachable publicly.

Why TCP/80 stays open

Let's Encrypt HTTP-01 validation starts on TCP/80 and retrieves a token under /.well-known/acme-challenge/. Keep TCP/80 reachable for issuance and renewal. After HTTPS is configured, port 80 can redirect ordinary requests to HTTPS.

Install and configure acme.sh

This runbook uses acme.sh in webroot mode. Webroot mode is appropriate because Apache is already serving the site and can expose the ACME challenge file without stopping the web server.

Define working variables

DOMAIN="<FQDN>"
EMAIL="<EMAIL>"
WEBROOT="/var/apache2/2.4/htdocs"
SSL_DIR="/etc/apache2/2.4/ssl"

export DOMAIN EMAIL WEBROOT SSL_DIR

Verify dependencies

which curl
which openssl
which crontab
openssl version



Resolve any missing tool before continuing.

pkg install archiver/gnu-tar

Install acme.sh

curl https://get.acme.sh | sh -s email="$EMAIL"

The installer normally places the client under the invoking user's ~/.acme.sh directory and creates a renewal cron entry.

For this runbook, installation is performed as root, so the expected path is:

/root/.acme.sh/acme.sh

Verify acme.sh

/root/.acme.sh/acme.sh --version
/root/.acme.sh/acme.sh --help | head

Select Let's Encrypt explicitly

/root/.acme.sh/acme.sh   --set-default-ca   --server letsencrypt

acme.sh supports multiple certificate authorities; this command explicitly selects Let's Encrypt.

Validate the HTTP-01 challenge path

Create the challenge directory

mkdir -p "$WEBROOT/.well-known/acme-challenge"
echo "ACME test OK" > "$WEBROOT/.well-known/acme-challenge/test.txt"

Test locally by hostname

curl "http://$DOMAIN/.well-known/acme-challenge/test.txt"

Expected:

ACME test OK



Test from an external network

Open the following URL from a device outside the OCI VCN:

http://<FQDN>/.well-known/acme-challenge/test.txt

Do not request a production certificate until this URL works from the public Internet.

Issue the Let's Encrypt certificate

Optional staging test

Before production issuance, a staging test is useful when you are still validating DNS, webroot permissions, or redirects. With current acme.sh, use the Let's Encrypt staging CA alias explicitly:

/root/.acme.sh/acme.sh   --issue   --server letsencrypt_test   -d "$DOMAIN"   -w "$WEBROOT"

Staging certificates are not browser-trusted. After a successful staging test, issue a production certificate.

Issue the production certificate

/root/.acme.sh/acme.sh   --issue   --server letsencrypt   -d "$DOMAIN"   -w "$WEBROOT"

acme.sh defaults to an ECC certificate unless a different key type is requested.

List managed certificates

/root/.acme.sh/acme.sh --list

Install the certificate into stable Apache TLS paths

Do not configure Apache to read certificate files directly from the internal ~/.acme.sh hierarchy. Use acme.sh --install-cert to copy the key and full chain to stable production paths and record the Apache reload command.

Create the TLS directory and files

mkdir -p "$SSL_DIR"
chmod 700 "$SSL_DIR"

touch "$SSL_DIR/$DOMAIN.key"
touch "$SSL_DIR/$DOMAIN.fullchain.pem"

chmod 600 "$SSL_DIR/$DOMAIN.key"
chmod 644 "$SSL_DIR/$DOMAIN.fullchain.pem"

Install the certificate

/root/.acme.sh/acme.sh \
  --install-cert \
  -d "$DOMAIN" \
  --key-file "$SSL_DIR/$DOMAIN.key" \
  --fullchain-file "$SSL_DIR/$DOMAIN.fullchain.pem" \
  --reloadcmd "svcadm restart svc:/network/http:apache24"

This also records the reload action for future renewals.

Inspect the certificate

openssl x509 \
  -in "$SSL_DIR/$DOMAIN.fullchain.pem" \
  -noout -subject -issuer -dates


 Note that apache runs as user "webservd" we need to apply proper permissions to the certificate files accordingly.

Enable SSL/TLS in Apache

Confirm the SSL module state

/usr/apache2/2.4/bin/httpd -M | grep ssl
grep -n 'ssl_module' /etc/apache2/2.4/httpd.conf

If ssl_module is already listed by httpd -M, continue. If the httpd.conf contains a commented LoadModule ssl_module line, back up the file and uncomment that existing line rather than inventing a module path.

Back up Apache configuration

cp -p /etc/apache2/2.4/httpd.conf   /etc/apache2/2.4/httpd.conf.pre-https

Enable the packaged ssl_module when needed

Edit:

vi /etc/apache2/2.4/httpd.conf

Find the existing ssl_module LoadModule directive and remove the leading #. Then validate:

/usr/apache2/2.4/bin/apachectl configtest
/usr/apache2/2.4/bin/httpd -M | grep ssl

Required syntax result:

Syntax OK

Confirm conf.d inclusion

grep -n 'Include' /etc/apache2/2.4/httpd.conf

If the packaged configuration already includes /etc/apache2/2.4/conf.d/*.conf, use that directory. If it does not, add an IncludeOptional directive only after reviewing the local httpd.conf layout.

Check for an existing port 443 listener directive

grep -R "^[[:space:]]*Listen[[:space:]]\+443"   /etc/apache2/2.4 2>/dev/null

Avoid adding a duplicate Listen 443 directive.

Create the HTTPS VirtualHost

cat > /etc/apache2/2.4/conf.d/solaris-web-ssl.conf <<EOF
Listen 443

<VirtualHost *:443>
    ServerName ${DOMAIN}
    DocumentRoot "${WEBROOT}"

    SSLEngine on
    SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1

    SSLCertificateFile "${SSL_DIR}/${DOMAIN}.fullchain.pem"
    SSLCertificateKeyFile "${SSL_DIR}/${DOMAIN}.key"

    ErrorLog "/var/apache2/2.4/logs/${DOMAIN}-ssl-error.log"
    CustomLog "/var/apache2/2.4/logs/${DOMAIN}-ssl-access.log" combined
</VirtualHost>
EOF

If Listen 443 already exists: Remove the Listen 443 line from this custom file and keep the existing listener directive. Apache must have only the listener configuration that your local package layout expects.

 

Validate and restart Apache

/usr/apache2/2.4/bin/apachectl configtest
svcadm restart svc:/network/http:apache24
svcs -xv svc:/network/http:apache24

Do not continue if configtest reports an error.

Verify port 443

netstat -an -P tcp | egrep '\.(80|443) '
pfctl -sr | egrep 'port = (22|80|443)'

You should see listeners on both web ports and PF pass rules for 80 and 443.

Validate HTTPS

Test with curl

curl -I "https://$DOMAIN/"

Expected status is HTTP 200 or another intentional application response without a TLS trust error.

Inspect the certificate presented by Apache

openssl s_client \
  -connect "${DOMAIN}:443" \
  -servername "${DOMAIN}" \
  </dev/null 2>/dev/null | \
openssl x509 -noout -subject -issuer -dates

Test from a browser

Open:

https://<FQDN>/

Verify the certificate is trusted and its subject/SAN contains the requested FQDN.


Redirect HTTP to HTTPS

Enable the redirect only after HTTPS is working. TCP/80 remains open because Let's Encrypt HTTP-01 begins on port 80 and can follow appropriate redirects.

Create an HTTP VirtualHost

cat > /etc/apache2/2.4/conf.d/solaris-web-http.conf <<EOF
<VirtualHost *:80>
    ServerName ${DOMAIN}
    DocumentRoot "${WEBROOT}"
    Redirect permanent / https://${DOMAIN}/
</VirtualHost>
EOF

Validate and restart

/usr/apache2/2.4/bin/apachectl configtest
svcadm restart svc:/network/http:apache24
svcs -xv apache24

Verify the redirect

curl -I "http://$DOMAIN/"

Expected response is a 301/302 redirect with a Location header pointing to https://<FQDN>/.

Automatic certificate renewal

Confirm the cron entry

crontab -l | grep acme.sh

The acme.sh installer normally creates a daily cron job that checks certificate renewal state.

Confirm Solaris cron is online

svcs svc:/system/cron:default

If required:

svcadm enable svc:/system/cron:default

Run the ACME cron handler manually

/root/.acme.sh/acme.sh   --cron   --home /root/.acme.sh

A normal run can report that the certificate is not due for renewal.

Verify reload integration

Because --install-cert stored the command svcadm restart svc:/network/http:apache24, a successful renewal can copy the updated certificate to the production path and restart Apache so the new certificate is presented.

Persistence and reboot validation

Pre-reboot checks

date
nlsadm get-timezone
svcs apache24
svcs network/firewall
svcprop -p firewall/rules svc:/network/firewall:default
pfctl -sr | egrep 'port = (22|80|443)'
netstat -an -P tcp | egrep '\.(80|443) '

Reboot

init 6

Reconnect after the instance is available.

Post-reboot checks

date
nlsadm get-timezone
svcs apache24
svcs network/firewall
svcprop -p firewall/rules svc:/network/firewall:default
pfctl -sr | egrep 'port = (22|80|443)'
netstat -an -P tcp | egrep '\.(80|443) '
curl -I "https://<FQDN>/"

This validates timezone, SMF service enablement, PF persistence, Apache listeners, and TLS after a full reboot.


 

Final health-check command set

Run as root after deployment:

echo "===== OS ====="
cat /etc/release | head -5

echo
echo "===== TIME ====="
date

echo
echo "===== TIMEZONE ====="
nlsadm get-timezone

echo
echo "===== NETWORK ====="
ipadm show-addr -p -o ADDROBJ,ADDR

echo
echo "===== APACHE PACKAGE ====="
pkg list web/server/apache-24

echo
echo "===== APACHE ====="
svcs apache24

echo
echo "===== FIREWALL ====="
svcs network/firewall

echo
echo "===== PF CONFIG FILE ====="
svcprop -p firewall/rules svc:/network/firewall:default

echo
echo "===== FIREWALL RULES ====="
pfctl -sr | egrep 'port = (22|80|443)'

echo
echo "===== LISTENERS ====="
netstat -an -P tcp | egrep '\.(80|443) '

echo
echo "===== APACHE CONFIG ====="
/usr/apache2/2.4/bin/apachectl configtest

echo
echo "===== HTTP ====="
curl -I "http://<FQDN>/"

echo
echo "===== HTTPS ====="
curl -I "https://<FQDN>/"

echo
echo "===== ACME ====="
/root/.acme.sh/acme.sh --list

echo
echo "===== ACME CRON ====="
crontab -l | grep acme.sh

Troubleshooting

Apache is disabled

svcs -a | grep apache
svcadm enable svc:/network/http:apache24
svcs -xv svc:/network/http:apache24

Apache enters maintenance

svcs -xv svc:/network/http:apache24
/usr/apache2/2.4/bin/apachectl configtest
tail -100 /var/apache2/2.4/logs/error_log

Correct the underlying problem, then:

svcadm clear svc:/network/http:apache24

HTTP works locally but not through the public IP

1. Confirm curl http://<PRIVATE_IP>/ returns a response.

2. Confirm netstat shows *.80 LISTEN.

3. Confirm pfctl -sr contains a TCP/80 pass rule.

4. Confirm the VNIC is attached to the intended NSG.

5. Confirm the NSG or Security List permits TCP/80.

6. Confirm the subnet route table has 0.0.0.0/0 to an enabled Internet Gateway.

7. Confirm the public IP is assigned to the private IP used by the VNIC.

8. Run snoop -d net0 port 80 while testing externally.

Editing pf_web.conf returns 'Insufficient privileges'

Check both POSIX permissions and Solaris special attributes:

ls -l /etc/firewall/pf_web.conf
ls -l/v /etc/firewall/pf_web.conf

If normal permissions are writable but the attribute list contains readonly:

chmod S-cR /etc/firewall/pf_web.conf
chmod 644 /etc/firewall/pf_web.conf

This exact condition was encountered in the validated deployment.

PF rule syntax failure

pfctl -nf /etc/firewall/pf_web.conf
tail -100 /var/svc/log/network-firewall:default.log

Do not restart the firewall service until the rules file passes pfctl -nf.

Port 443 does not listen

/usr/apache2/2.4/bin/apachectl configtest
/usr/apache2/2.4/bin/httpd -M | grep ssl
grep -R "^[[:space:]]*Listen[[:space:]]\+443" /etc/apache2/2.4 2>/dev/null
svcs -xv apache24
tail -100 /var/apache2/2.4/logs/error_log

Check for an unloaded ssl_module, duplicate Listen 443 directives, invalid certificate paths, or unreadable key files.

Let's Encrypt HTTP-01 fails

1. Confirm <FQDN> resolves publicly to the OCI public IP.

2. Confirm http://<FQDN>/.well-known/acme-challenge/test.txt is reachable externally.

3. Confirm TCP/80 is allowed by the OCI NSG/Security List.

4. Confirm TCP/80 is allowed by Solaris PF.

5. Confirm Apache is serving the expected WEBROOT.

6. Check for redirects that route the ACME path to an unrelated host.

7. Use Let's Encrypt staging while troubleshooting to avoid production rate-limit pressure.

Certificate renews but browser still shows the old certificate

openssl x509 -in "$SSL_DIR/$DOMAIN.fullchain.pem" -noout -dates
/root/.acme.sh/acme.sh --list
svcadm restart svc:/network/http:apache24

Confirm that --install-cert was configured with the production paths and the Solaris SMF reload command.

Rollback procedure

Roll back Apache HTTPS configuration

mv /etc/apache2/2.4/conf.d/solaris-web-ssl.conf    /etc/apache2/2.4/conf.d/solaris-web-ssl.conf.disabled

mv /etc/apache2/2.4/conf.d/solaris-web-http.conf    /etc/apache2/2.4/conf.d/solaris-web-http.conf.disabled

/usr/apache2/2.4/bin/apachectl configtest
svcadm restart svc:/network/http:apache24

If you changed httpd.conf to enable ssl_module and must fully revert, restore the recorded pre-HTTPS backup after reviewing any later changes.

Roll back PF to the original SSH-only policy

Warning: This removes web access on TCP/80 and TCP/443. Keep an active SSH session and confirm that the original SSH rule exists before applying the rollback.

 

pfctl -nf /etc/firewall/pf_ssh_only.conf
pfctl -f /etc/firewall/pf_ssh_only.conf

svccfg -s svc:/network/firewall:default \
  setprop firewall/rules = astring: /etc/firewall/pf_ssh_only.conf

svcadm refresh svc:/network/firewall:default
svcadm restart svc:/network/firewall:default

svcprop -p firewall/rules svc:/network/firewall:default
pfctl -sr

Security recommendations

·         Restrict OCI TCP/22 to the administrator's trusted public CIDR rather than 0.0.0.0/0.

·         Keep the Solaris PF default-deny policy and add only required inbound services.

·         Protect the TLS private key with root ownership and mode 600.

·         Retain TCP/80 for HTTP-01 validation and redirect normal HTTP requests to HTTPS.

·         Use an OCI Reserved Public IP when DNS and TLS depend on a stable endpoint.

·         Keep Solaris SRUs and Apache packages current through approved maintenance procedures.

·         Review /var/apache2/2.4/logs and the PF service log during operational monitoring.

·         Test ACME changes against Let's Encrypt staging before repeated production issuance attempts.

Deployment checklist

☐ OCI public subnet is routed to an enabled Internet Gateway.

☐ Solaris VNIC has the intended public IPv4 address.

☐ NSG permits TCP/22 from the administrator /32.

☐ NSG permits TCP/80 and TCP/443 from the required sources.

☐ Solaris reports timezone=Asia/Kolkata.

☐ Apache package web/server/apache-24 is installed.

☐ svc:/network/http:apache24 is online.

☐ Static page returns HTTP 200 from localhost and the private IP.

☐ Solaris firewall service is online.

☐ PF persistent file is /etc/firewall/pf_web.conf.

☐ PF contains TCP/22, TCP/80 and TCP/443 pass rules.

☐ Public HTTP access succeeds.

☐ DNS A record for <FQDN> resolves to the OCI public IP.

☐ ACME challenge test file is reachable from the public Internet.

☐ Let's Encrypt certificate has been issued.

☐ Certificate is installed under /etc/apache2/2.4/ssl.

☐ Apache ssl_module is loaded.

☐ Apache listens on TCP/443.

☐ HTTPS returns a trusted certificate.

☐ HTTP redirects to HTTPS.

☐ acme.sh renewal cron entry exists.

☐ Post-reboot validation succeeds.

Official references

Oracle Solaris 11.4 - Apache HTTP Server installation and SMF enablement: https://docs.oracle.com/en/operating-systems/solaris/oracle-solaris/11.4/config-app-dev/introduction-setting-up-application-development-environment-oracle-solaris-11.html

Oracle Solaris 11.4 - Apache configuration paths: https://docs.oracle.com/cd/E37838_01/html/E60982/apache-config.html

Oracle Solaris 11.4 - PF firewall configuration: https://docs.oracle.com/cd/E37838_01/html/E60993/pftask-conf.html

Oracle Solaris 11.4 - PF rules file and firewall/rules SMF property: https://docs.oracle.com/cd/E37838_01/html/E60993/pfovw-files.html

Oracle Solaris 11.4 - PF administration with pfctl: https://docs.oracle.com/cd/E37838_01/html/E60993/pftask-pfctl.html

Oracle Solaris 11.4 - ZFS special file attributes: https://docs.oracle.com/en/operating-systems/solaris/oracle-solaris/11.4/secure-files/displaying-and-changing-zfs-file-attributes.html

Let's Encrypt - Challenge Types / HTTP-01: https://letsencrypt.org/docs/challenge-types/

Let's Encrypt - Keep Port 80 Open: https://letsencrypt.org/docs/allow-port-80/

acme.sh official project: https://github.com/acmesh-official/acme.sh

Validated session notes

Observation

Validated result

Timezone before change

UTC

Timezone after change

Asia/Kolkata / IST

Apache package

web/server/apache-24 already installed

Apache version

2.4.67

Apache config test

Syntax OK

Apache SMF

svc:/network/http:apache24 online

Private address

172.16.10.186/24 on net0

Local HTTP

HTTP/1.1 200 OK

Firewall SMF

svc:/network/firewall:default online

Original persistent rules

/etc/firewall/pf_ssh_only.conf

Original inbound policy

SSH allowed; HTTP blocked

Custom rules file

/etc/firewall/pf_web.conf

Special attribute issue

Copy inherited readonly; normal chmod alone did not permit writes

Resolved PF policy

TCP/22 and TCP/80 verified; runbook extends policy to TCP/443

External HTTP

Successfully displayed through the OCI public IP

 


Comments

Popular posts from this blog

Access Oracle OCI Object Storage through GUI Client

Instance OS Baseline Configuration Runbook

Accessing OCI Compute Instances Using VNC Console (Instance Console Connection)