

<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>letsencrypt &#8211; Max的程式語言筆記</title>
	<atom:link href="https://stackoverflow.max-everyday.com/tag/letsencrypt/feed/" rel="self" type="application/rss+xml" />
	<link>https://stackoverflow.max-everyday.com</link>
	<description>我要當一個豬頭，快樂過每一天</description>
	<lastBuildDate>Thu, 06 May 2021 08:30:11 +0000</lastBuildDate>
	<language>zh-TW</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.1</generator>

<image>
	<url>https://stackoverflow.max-everyday.com/wp-content/uploads/2017/02/max-stackoverflow-256.png</url>
	<title>letsencrypt &#8211; Max的程式語言筆記</title>
	<link>https://stackoverflow.max-everyday.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>同一台伺服器增加多個網站</title>
		<link>https://stackoverflow.max-everyday.com/2020/10/add-new-wordpress-site-on-exist-server/</link>
					<comments>https://stackoverflow.max-everyday.com/2020/10/add-new-wordpress-site-on-exist-server/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Mon, 12 Oct 2020 13:13:14 +0000</pubDate>
				<category><![CDATA[WordPress筆記]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[letsencrypt]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">http://stackoverflow.max-everyday.com/?p=3539</guid>

					<description><![CDATA[反正買了一個domain 可以隨意增加 sub ...]]></description>
										<content:encoded><![CDATA[
<p>反正買了一個domain 可以隨意增加 sub domain(子網域)， 今天要來示範如果從無到有，增加一個有SSL的 WordPress 網站。這次要新增的網站是 krita.max-everyday.com</p>



<p><strong>Step 1：設定 mysql 資料庫</strong></p>



<p>在 mysql 裡增加新的database: krita，並一組帳號給新的站台登入使用。可以參考下列的 sql command:</p>



<pre class="wp-block-preformatted">create database krita;
CREATE USER 'kritauser1'@'localhost' IDENTIFIED BY 'your-krita-user-password';
GRANT ALL PRIVILEGES ON krita.* TO kritauser1@localhost;
FLUSH PRIVILEGES;</pre>



<p><strong>Step 2：設定 WordPress</strong></p>



<p>複製一份空的 wordpress source code 到 /var/www/krtia 目錄下，最後修改 wp-config.php ，修改下面的這3個欄位內容：</p>



<pre class="wp-block-preformatted">define('DB_NAME', 'krita');
<em>define('DB_USER', 'kritauser1');</em>
define('DB_PASSWORD', 'your-krita-user-password');</pre>



<p>還有把 source code 的所有權設定給 www-data 讓更新和下載 php 的主題、佈景和外掛會方便一些。</p>



<p>chown -R www-data:www-data .</p>



<p><strong>Step 3：修改 /etc/hosts 檔案</strong></p>



<p>增加</p>



<pre class="wp-block-preformatted">127.0.0.1 krita.max-everyday.com</pre>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="648" height="275" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-12-at-19.45.53.png" alt="" class="wp-image-3540" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-12-at-19.45.53.png?v=1602504072 648w, https://stackoverflow.max-everyday.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-12-at-19.45.53-600x255.png?v=1602504072 600w" sizes="(max-width: 648px) 100vw, 648px" /></figure>



<p><strong>Step 4：在 Apache 增加新站台</strong></p>



<p>在 /etc/apache2/sites-available 裡增加一個新的 web 站台。</p>



<p>這個可以使用第一個預設站台裡的內容，直接 copy 為新的檔名，例如：</p>



<pre class="wp-block-preformatted">cp 000-default.conf 114-krita.conf</pre>



<p>修改 114-krita.conf 檔案內容：</p>



<ul class="wp-block-list"><li>DocumentRoot /var/www/krita</li><li>&lt;Directory /var/www/krita</li><li>ServerName krita.max-everyday.com</li></ul>



<p>到 /etc/apache2/sites-enabled/ 目錄下，使用下面指令，增加一個 enable 的 web site:</p>



<pre class="wp-block-preformatted">ln -s ../sites-available/114-krita.conf 114-krita.conf</pre>



<p><strong>Step 5：重啟 apache</strong></p>



<p>服用下列指令：</p>



<pre class="wp-block-preformatted">service apache2 restart</pre>



<p><strong>Step 6：在DNS 增加子網域</strong></p>



<p>增加 A Record</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="491" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-12-at-20.10.02-1024x491.png?v=1602504773" alt="" class="wp-image-3541" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-12-at-20.10.02-1024x491.png?v=1602504773 1024w, https://stackoverflow.max-everyday.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-12-at-20.10.02-600x288.png?v=1602504773 600w, https://stackoverflow.max-everyday.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-12-at-20.10.02-768x369.png?v=1602504773 768w, https://stackoverflow.max-everyday.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-12-at-20.10.02-1536x737.png?v=1602504773 1536w, https://stackoverflow.max-everyday.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-12-at-20.10.02-2048x983.png?v=1602504773 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>proxy 狀態的欄位，先點一下，切換為「僅DNS」(DNS only)，暫時不需要對內容做快取。</p>



<p><strong>Step 7：取得 SSL 憑證</strong></p>



<p>服用下面的指令：</p>



<pre class="wp-block-preformatted">certbot --apache</pre>



<p>執行畫面：</p>



<figure class="wp-block-image size-large"><img decoding="async" width="473" height="440" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-12-at-20.21.52.png" alt="" class="wp-image-3542"/></figure>



<p>這時候，輸入 10 再按 Enter 就會接著問，要不要重導 http 的 URL 到  https，選1或選 2都行，我是選1。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="720" height="807" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-12-at-20.29.12.jpg" alt="" class="wp-image-3543" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-12-at-20.29.12.jpg?v=1602506033 720w, https://stackoverflow.max-everyday.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-12-at-20.29.12-535x600.jpg?v=1602506033 535w" sizes="(max-width: 720px) 100vw, 720px" /></figure>



<p><strong>Step 8：完成</strong></p>



<p>連到  https://krita.max-everyday.com 就可以開始設定 WordPress 站台。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="964" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2020/10/multi-wordpress-site-1024x964.png?v=1602508380" alt="" class="wp-image-3545" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2020/10/multi-wordpress-site-1024x964.png?v=1602508380 1024w, https://stackoverflow.max-everyday.com/wp-content/uploads/2020/10/multi-wordpress-site-600x565.png?v=1602508380 600w, https://stackoverflow.max-everyday.com/wp-content/uploads/2020/10/multi-wordpress-site-768x723.png?v=1602508380 768w, https://stackoverflow.max-everyday.com/wp-content/uploads/2020/10/multi-wordpress-site-1536x1445.png?v=1602508380 1536w, https://stackoverflow.max-everyday.com/wp-content/uploads/2020/10/multi-wordpress-site.png?v=1602508380 1560w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2020/10/add-new-wordpress-site-on-exist-server/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Why isn’t my certificate trusted in Android?</title>
		<link>https://stackoverflow.max-everyday.com/2017/03/why-isnt-my-certificate-trusted-in-android/</link>
					<comments>https://stackoverflow.max-everyday.com/2017/03/why-isnt-my-certificate-trusted-in-android/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Sun, 05 Mar 2017 11:21:44 +0000</pubDate>
				<category><![CDATA[電腦相關應用]]></category>
		<category><![CDATA[letsencrypt]]></category>
		<guid isPermaLink="false">http://stackoverflow.max-everyday.com/?p=315</guid>

					<description><![CDATA[&#160; 今天發現 LetsEncrypt ...]]></description>
										<content:encoded><![CDATA[<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-316" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2017/03/letsencrypt-android-ssl-error.jpg" alt="" width="1280" height="1200" /></p>
<p>&nbsp;</p>
<p>今天發現 LetsEncrypt ＋ Nginx 在 Android 裡的所有瀏覽器都會顯示憑證不合法。解法是不要去使用 cert.pem 而是改用 fullchain.pem, 滿神奇的，LetsEncrypt ＋Apache 在 Android  是用 cert.pem 就可以合法了。</p>
<h2>NGINX</h2>
<div class="highlight highlight-source-nginx">
<pre><span class="pl-k">server</span> {
    <span class="pl-k">listen</span>              <span class="pl-s">443</span> ssl;
    <span class="pl-k">server_name</span>         example.com;
    <span class="pl-k">ssl_certificate</span>     /etc/letsencrypt/live/example.com/fullchain.pem;
    <span class="pl-k">ssl_certificate_key</span> /etc/letsencrypt/live/example.com/privkey.pem;
}

</pre>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2017/03/why-isnt-my-certificate-trusted-in-android/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>apache AH00171: Graceful restart requested, doing restart</title>
		<link>https://stackoverflow.max-everyday.com/2017/02/apache-graceful-restart/</link>
					<comments>https://stackoverflow.max-everyday.com/2017/02/apache-graceful-restart/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Tue, 07 Feb 2017 12:46:57 +0000</pubDate>
				<category><![CDATA[電腦相關應用]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[DigitalOcean]]></category>
		<category><![CDATA[letsencrypt]]></category>
		<category><![CDATA[linux]]></category>
		<guid isPermaLink="false">http://stackoverflow.max-everyday.com/?p=100</guid>

					<description><![CDATA[自從安裝了 nginx 之後，apache 的 ...]]></description>
										<content:encoded><![CDATA[<p>自從安裝了 nginx 之後，apache 的 service 每天都自動地被關閉。</p>
<p>用下面指令查看 apache log:</p>
<blockquote><p>tail -n 15 /var/log/apache2/error.log</p></blockquote>
<hr />
<pre>[Tue Feb 07 00:00:35.176718 2017] [mpm_prefork:notice] [pid 1393] AH00171: Graceful restart requested, doing restart
AH00112: Warning: DocumentRoot [/var/lib/letsencrypt/tls_sni_01_page/] does not exist
AH00112: Warning: DocumentRoot [/var/lib/letsencrypt/tls_sni_01_page/] does not exist
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' directive globally to suppress this message
(98)Address already in use: AH00072: make_sock: could not bind to address [::]:443
(98)Address already in use: AH00072: make_sock: could not bind to address 0.0.0.0:443
[Tue Feb 07 00:00:35.374235 2017] [mpm_prefork:alert] [pid 1393] no listening sockets available, shutting down
[Tue Feb 07 00:00:35.374243 2017] [:emerg] [pid 1393] AH00019: Unable to open logs, exiting
[Tue Feb 07 00:00:43.772645 2017] [core:warn] [pid 7398] AH00098: pid file /var/run/apache2/apache2.pid overwritten -- Unclean shutdown of previous Apache run?
[Tue Feb 07 00:00:43.774845 2017] [mpm_prefork:notice] [pid 7398] AH00163: Apache/2.4.18 (Ubuntu) OpenSSL/1.0.2g configured -- resuming normal operations
[Tue Feb 07 00:00:43.774879 2017] [core:notice] [pid 7398] AH00094: Command line: '/usr/sbin/apache2'
[Tue Feb 07 00:05:35.586000 2017] [mpm_prefork:notice] [pid 7398] AH00169: caught SIGTERM, shutting down
</pre>
<hr />
<p>查看 /etc/logrotate.d/apache2</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-101" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2017/02/Screenshot-2017-02-07-19.09.33.jpg" alt="" width="480" height="365" /></p>
<p>先修改上面的 /etc/init.d/apache2 reload 為 /etc/init.d/apache2 restart 之後，明天的 00:00 時候再試看看 apache 會不會又crash.</p>
<hr />
<p>結果隔了一天，還是又掛了，新的 Error Log 還是長一樣：</p>
<pre>[Wed Feb 08 00:00:33.919348 2017] [mpm_prefork:notice] [pid 12057] AH00171: Graceful restart requested, doing restart
AH00112: Warning: DocumentRoot [/var/lib/letsencrypt/tls_sni_01_page/] does not exist
AH00112: Warning: DocumentRoot [/var/lib/letsencrypt/tls_sni_01_page/] does not exist
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' directive globally to suppress this message
(98)Address already in use: AH00072: make_sock: could not bind to address [::]:443
(98)Address already in use: AH00072: make_sock: could not bind to address 0.0.0.0:443
[Wed Feb 08 00:00:34.029522 2017] [mpm_prefork:alert] [pid 12057] no listening sockets available, shutting down
[Wed Feb 08 00:00:34.029536 2017] [:emerg] [pid 12057] AH00019: Unable to open logs, exiting
[Wed Feb 08 00:00:42.448650 2017] [core:warn] [pid 16845] AH00098: pid file /var/run/apache2/apache2.pid overwritten -- Unclean shutdown of previous Apache run?
[Wed Feb 08 00:00:42.450795 2017] [mpm_prefork:notice] [pid 16845] AH00163: Apache/2.4.18 (Ubuntu) OpenSSL/1.0.2g configured -- resuming normal operations
[Wed Feb 08 00:00:42.450817 2017] [core:notice] [pid 16845] AH00094: Command line: '/usr/sbin/apache2'
[Wed Feb 08 00:00:52.544625 2017] [mpm_prefork:notice] [pid 16845] AH00169: caught SIGTERM, shutting down
</pre>
<p>&nbsp;</p>
<hr />
<p>在 /var 目錄下指令：</p>
<blockquote>
<pre class="p1"><span class="s1">grep -r 'tls_sni_01_page' *</span></pre>
</blockquote>
<p class="p1">發現是 <span class="s1">letsencrypt renew 的排程讓 apache2 掛掉。</span></p>
<p class="p1">重新研究一下 certbot 的指令：<br />
<a href="https://certbot.eff.org/docs/using.html#manual">https://certbot.eff.org/docs/using.html#manual</a></p>
<p>&nbsp;</p>
<p class="p1">發現使用 standalone 會啟動一個暫時的 web server  來取得憑證。</p>
<p><a href="https://certbot.eff.org/docs/using.html#standalone">https://certbot.eff.org/docs/using.html#standalone</a></p>
<pre>standalone:
  Spin up a temporary webserver</pre>
<hr />
<p class="p1">certonly 參數如下：</p>
<pre>certonly:
  Options for modifying how a cert is obtained

  <span style="color: #ff0000;">--tls-sni-01-port</span> TLS_SNI_01_PORT
                        Port used during tls-sni-01 challenge. This only
                        affects the port Certbot listens on. A conforming ACME
                        server will still attempt to connect on port 443.
                        (default: 443)
  <span style="color: #ff0000;">--http-01-port</span> HTTP01_PORT
                        Port used in the http-01 challenge.This only affects
                        the port Certbot listens on. A conforming ACME server
                        will still attempt to connect on port 80. (default:
                        80)
  --csr CSR             Path to a Certificate Signing Request (CSR) in DER or
                        PEM format. Currently --csr only works with the
                        'certonly' subcommand. (default: None)
</pre>
<hr />
<p>&nbsp;</p>
<blockquote>
<pre>certbot certonly --standalone -d example.com <span style="color: #ff0000;">--tls-sni-01-port 443 --http-01-port 80</span></pre>
</blockquote>
<p>新的版本的 certbot 用起來更簡單：</p>
<blockquote>
<pre>certbot certonly --cert-name your-domain-name</pre>
</blockquote>
<p>&nbsp;</p>
<p>nginx 請修改 config 裡：</p>
<pre><span class="Comment">  # 啟用 SSL</span>
  <span class="Identifier">ssl</span> <span class="Constant">on</span>;

<span class="Comment">  # 設定 SSL 憑證</span>
  <span class="Identifier">ssl_certificate</span> /etc/letsencrypt/live/your-domain-name/fullchain.pem;
  <span class="Identifier">ssl_certificate_key</span> /etc/letsencrypt/live/your-domain-name/privkey.pem;

</pre>
<p>&nbsp;</p>
<p>官方教學：</p>
<p><a href="https://certbot.eff.org/lets-encrypt/ubuntuxenial-other">https://certbot.eff.org/lets-encrypt/ubuntuxenial-other</a></p>
<p>&nbsp;</p>
<hr />
<h4>相關文章：</h4>
<p>How to know why my server crashes?<br />
<a href="http://askubuntu.com/questions/405655/how-to-know-why-my-server-crashes">http://askubuntu.com/questions/405655/how-to-know-why-my-server-crashes</a></p>
<p>Apache reload/graceful restart causes Apache segfault<br />
<a href="https://talk.plesk.com/threads/apache-reload-graceful-restart-causes-apache-segfault.335534/">https://talk.plesk.com/threads/apache-reload-graceful-restart-causes-apache-segfault.335534/</a></p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2017/02/apache-graceful-restart/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Gracefully handling application exceptions in a Tornado application</title>
		<link>https://stackoverflow.max-everyday.com/2017/02/handling-exceptions-tornado/</link>
					<comments>https://stackoverflow.max-everyday.com/2017/02/handling-exceptions-tornado/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Sun, 05 Feb 2017 19:40:00 +0000</pubDate>
				<category><![CDATA[Python筆記]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[letsencrypt]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[tornado]]></category>
		<guid isPermaLink="false">http://stackoverflow.max-everyday.com/?p=93</guid>

					<description><![CDATA[之前在DigitalOcean 的主機上用wor...]]></description>
										<content:encoded><![CDATA[<p>之前在DigitalOcean 的主機上用wordpress架了一個web site站台，只使用了 port 80, 後來在 443 port 架了 tornado, 滿神奇的，tornado 可以直接使用 letsencrypt 的憑證檔案。</p>
<p>後來發現 googlebot 會來parse 443 port 裡的資料。所以我希望 404 錯誤的資料就從80 port 裡重新取得一次，丟給Google.</p>
<hr />
<h4>取得 ssl 憑證</h4>
<p>首先，是 letsencrypt 的 certbot 的官方說明：<br />
<a href="https://certbot.eff.org/#ubuntuxenial-other">https://certbot.eff.org/#ubuntuxenial-other</a></p>
<p>照上面教學的指令下，只用一行就可以產生憑證。知道網站的根目錄用這行（指令1號）：</p>
<pre>letsencrypt certonly --webroot -w /var/www/example -d example.com
</pre>
<hr />
<p>如果你完全沒有網站，可以使用這行（指令2號）：</p>
<pre>letsencrypt certonly --standalone -d example.com -d www.example.com</pre>
<p>指令1號，letsencrypt 會放東西在 webroot 目錄裡，然後letsencrypt用 80 port 連回我們伺服器進去測試。</p>
<p>指令2號，會自動產生一個 80 port 的 service，然後letsencrypt用 80 port 連回我們伺服器進去測試。</p>
<p>這2個指令，都會因此去使用 443 port，實際上原理不需要了解太多，certbot 寫的滿聰明的，會在畫面上有提醒。產生完，手動測一下 renew，沒問題的把把 renew 指令放進排程裡。</p>
<pre>letsencrypt renew --dry-run --agree-tos</pre>
<p>成功後就會在ubuntu的/etc/letsencrypt/archive/ 下面看到憑證了。</p>
<p>&nbsp;</p>
<p>在 80和443 port 都已經被其他程式使用中的請況下，需要更進階的設定，參考看看這一篇：</p>
<p>apache AH00171: Graceful restart requested, doing restart<br />
<a href="https://stackoverflow.max-everyday.com/2017/02/apache-graceful-restart/">https://stackoverflow.max-everyday.com/2017/02/apache-graceful-restart/</a></p>
<p>例如：</p>
<pre>letsencrypt certonly --standalone -d example.com --tls-sni-01-port 445 --http-01-port 82</pre>
<hr />
<h4>修改Tornado的 ssl_options</h4>
<p>tornado改程式，須追加此兩個檔案的路徑在ssl_options下面，並注意檔案權限要能被讀。</p>
<p>http_server = tornado.httpserver.HTTPServer(Application(),<br />
ssl_options={<br />
&#8220;certfile&#8221;: &#8220;cert.pem&#8221;, #自行填好路徑<br />
&#8220;keyfile&#8221;: &#8220;privkey.pem&#8221;, #自行填好路徑<br />
})</p>
<p>完成之後，研究一下 tornado 的官方文件：<br />
<a href="http://www.tornadoweb.org/en/stable/web.html#tornado.web.Application.settings">http://www.tornadoweb.org/en/stable/web.html#tornado.web.Application.settings</a></p>
<hr />
<p>要使用下面的這組設定值來完成自動轉發：</p>
<ul class="simple">
<li><code class="docutils literal"><span class="pre">default_handler_class</span></code> and <code class="docutils literal"><span class="pre">default_handler_args</span></code>: This handler will be used if no other match is found; use this to implement custom 404 pages (new in Tornado 3.2).</li>
</ul>
<p>範例寫法：</p>
<pre class="lang-python prettyprint prettyprinted"><code><span class="kwd">import</span><span class="pln"> tornado</span><span class="pun">.</span><span class="pln">web


</span><span class="kwd">class</span> <span class="typ">BaseHandler</span><span class="pun">(</span><span class="pln">tornado</span><span class="pun">.</span><span class="pln">web</span><span class="pun">.</span><span class="typ">RequestHandler</span><span class="pun">):</span>
    <span class="str">"""
    Base handler gonna to be used instead of RequestHandler
    """</span>
    <span class="kwd">def</span><span class="pln"> write_error</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> status_code</span><span class="pun">,</span> <span class="pun">**</span><span class="pln">kwargs</span><span class="pun">):</span>
        <span class="kwd">if</span><span class="pln"> status_code </span><span class="kwd">in</span> <span class="pun">[</span><span class="lit">403</span><span class="pun">,</span> <span class="lit">404</span><span class="pun">,</span> <span class="lit">500</span><span class="pun">,</span> <span class="lit">503</span><span class="pun">]:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="str">'Error %s'</span> <span class="pun">%</span><span class="pln"> status_code</span><span class="pun">)</span>
        <span class="kwd">else</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="str">'BOOM!'</span><span class="pun">)</span>


<span class="kwd">class</span> <span class="typ">ErrorHandler</span><span class="pun">(</span><span class="pln">tornado</span><span class="pun">.</span><span class="pln">web</span><span class="pun">.</span><span class="typ">ErrorHandler</span><span class="pun">,</span> <span class="typ">BaseHandler</span><span class="pun">):</span>
    <span class="str">"""
    Default handler gonna to be used in case of 404 error
    """</span>
    <span class="kwd">pass</span>


<span class="kwd">class</span> <span class="typ">MainHandler</span><span class="pun">(</span><span class="typ">BaseHandler</span><span class="pun">):</span>
    <span class="str">"""
    Main handler
    """</span>
    <span class="kwd">def</span><span class="pln"> get</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="str">'Hello world!'</span><span class="pun">)</span></code></pre>
<ol start="2">
<li>Settings. We need to define <code>default_handler_class</code> and <code>default_handler_args</code> as well</li>
</ol>
<pre class="lang-python prettyprint prettyprinted"><code><span class="pln">settings </span><span class="pun">=</span> <span class="pun">{</span>
    <span class="str">'default_handler_class'</span><span class="pun">:</span> <span class="typ">ErrorHandler</span><span class="pun">,</span>
    <span class="str">'default_handler_args'</span><span class="pun">:</span><span class="pln"> dict</span><span class="pun">(</span><span class="pln">status_code</span><span class="pun">=</span><span class="lit">404</span><span class="pun">)</span>
<span class="pun">}</span></code></pre>
<ol start="3">
<li>Application.</li>
</ol>
<pre class="lang-python prettyprint prettyprinted"><code><span class="pln">application </span><span class="pun">=</span><span class="pln"> tornado</span><span class="pun">.</span><span class="pln">web</span><span class="pun">.</span><span class="typ">Application</span><span class="pun">([</span>
    <span class="pun">(</span><span class="pln">r</span><span class="str">"/"</span><span class="pun">,</span> <span class="typ">MainHandler</span><span class="pun">)</span>
<span class="pun">],</span> <span class="pun">**</span><span class="pln">settings</span><span class="pun">)</span></code></pre>
<p>as result. all errors except 404 gonna be handled by BaseHandler. 404 &#8211; ErrorHandler. that&#8217;s it <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<hr />
<p>我的轉發的 code:</p>
<pre>def write_error(self, status_code, **kwargs):
    if status_code == 404:
        from lib import libHttp
        http_obj = libHttp.Http()
        http_url = "http://%s%s" % (self.request.host,self.request.uri)
        (new_html_string, http_code) = http_obj.get_http_response(http_url)
        self.set_status(http_code)
        if not new_html_string is None:
            self.write(new_html_string)
        return
    return super(BaseHandler, self).write_error(status_code, **kwargs)

</pre>
<hr />
<p>我最後放棄這個作法，改安裝 Nginx（發音同engine x）是一個網頁伺服器，它能反向代理HTTP, HTTPS, SMTP, POP3, IMAP的協議鏈接，以及一個負載均衡器和一個HTTP緩存。</p>
<p><a href="https://www.nginx.com/resources/wiki/start/topics/tutorials/install/">https://www.nginx.com/resources/wiki/start/topics/tutorials/install/</a></p>
<p>範例：</p>
<p>nginx 基礎設定教學<br />
<a href="http://blog.hellojcc.tw/2015/12/07/nginx-beginner-tutorial/">http://blog.hellojcc.tw/2015/12/07/nginx-beginner-tutorial/</a></p>
<p>&nbsp;</p>
<hr />
<h4>相關文章：</h4>
<p>apache AH00171: Graceful restart requested, doing restart<br />
<a href="https://stackoverflow.max-everyday.com/2017/02/apache-graceful-restart/">https://stackoverflow.max-everyday.com/2017/02/apache-graceful-restart/</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2017/02/handling-exceptions-tornado/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>安裝/設定/移除免費的 Let&#8217;s Encrypt  HTTPS 憑證</title>
		<link>https://stackoverflow.max-everyday.com/2017/01/lets-encrypt-free-https/</link>
					<comments>https://stackoverflow.max-everyday.com/2017/01/lets-encrypt-free-https/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Fri, 06 Jan 2017 00:24:08 +0000</pubDate>
				<category><![CDATA[WordPress筆記]]></category>
		<category><![CDATA[電腦相關應用]]></category>
		<category><![CDATA[DigitalOcean]]></category>
		<category><![CDATA[letsencrypt]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">http://stackoverflow.max-everyday.com/?p=155</guid>

					<description><![CDATA[之前架設的 WordPress 只有 http ...]]></description>
										<content:encoded><![CDATA[
<p>之前架設的 WordPress 只有 http 沒有https, 沒想到居然可以超簡單地就申請好多個 https在同一台主機。</p>



<p>Let&#8217;s Encrypt 的工具程式「取得」和「操作」說明：<br><a href="https://certbot.eff.org/">https://certbot.eff.org/</a></p>



<p class="has-vivid-red-color has-text-color">請先在上面的官方網頁裡，選擇需要running的 web server 的 platform 後，先安裝 certbot。</p>



<hr class="wp-block-separator"/>



<p>CertBot真的是很棒的一個網站，會依照不同的作業系統給不同的指令。CertBot滿厲害的，不帶參數，他也可以猜到要產生的domain name，我是透過下面的指令，可以一次加入 2個domain 的 https 憑證到 apache 裡了：</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>certbot certonly&nbsp; -w /var/www/example -d example.com</p></blockquote>



<p>上面是古時候的作法，需要自己下指令，目前的程式變的很先進和聰明，只要直接輸入：</p>



<pre class="wp-block-preformatted">certbot </pre>



<p>就有選單，可以直接做選擇，要對那一個 domain 做申請，還有做設定要不要強制http redirect to https.</p>



<hr class="wp-block-separator"/>



<p>對完全都還沒有 ssl 的情況，直接打 certbot 是可以完成。可是已有 ssl ，要幫 sub domain 申請 ssl 時，請先 enable http 的 site 就好，ssl 的 site 不要自己去 新增，使用 certbot 自己新增即可，如果 web server 是 apache 建議使用指令：</p>



<pre class="wp-block-preformatted">certbot --apache</pre>



<p>如果一直鬼打接申請不過去，也可以試看看先停用 apache 後，執行下面的指令來申請 sub domain 的憑證：</p>



<pre class="wp-block-preformatted">certbot certonly <strong>--</strong>webroot <strong>-</strong>w <strong>/</strong>var<strong>/</strong>www<strong>/</strong>example <strong>-</strong>d www<strong>.</strong>example<strong>.</strong>com</pre>



<hr class="wp-block-separator"/>



<p>真是太感動了，我的網站也有 https 了。</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1602" height="956" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2017/01/Screenshot-2017-01-06-13.14.31.jpg" alt="" class="wp-image-158"/></figure>



<h3 class="wp-block-heading">Automating renewal （自動展期的指令）</h3>



<p>Certbot can be configured to renew your certificates automatically before they expire. Since Let&#8217;s Encrypt certificates last for 90 days, it&#8217;s highly advisable to take advantage of this feature. You can test automatic renewal for your certificates by running this command:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>letsencrypt renew &#8211;dry-run &#8211;agree-tos</p></blockquote>



<p>如預期，在 Ubuntu 16.04 會多顯示一些錯誤訊息，但不影影展期。</p>



<p>把上面的指令放到排程裡，讓電腦每天自動執行，快到期的時候就會自動展期了。</p>



<p>如果遇到問題，可以點 &#8220;Advance&#8221; 裡，只使用取得憑證的指令。</p>



<p>有了 letsencrypt 的憑證之後，如果遇到bot 無法自動修改 apache 設定檔的情況，我是都自己修改比較多，請加入下面紅字部份的設定：</p>



<pre class="wp-block-preformatted">&lt;VirtualHost *:443&gt;
    ServerName max-everyday.com
    DocumentRoot /var/www/max-everyday.com/public_html
    ErrorLog /var/log/apache/max-everyday.com/error.log
    CustomLog /var/log/apache/max-everyday.com/access.log combined

	SSLEngine on 
	SSLCertificateFile /etc/letsencrypt/live/max-everyday.com/cert.pem
	SSLCertificateKeyFile /etc/letsencrypt/live/max-everyday.com/privkey.pem
	SSLCertificateChainFile /etc/letsencrypt/live/max-everyday.com/chain.pem
&lt;/VirtualHost&gt;
</pre>



<hr class="wp-block-separator"/>



<p>除了免費的 https, 記得網站還要使用免費的CloudFlare CDN，這樣顯示才會「超級快」。</p>



<p>Cloudflare<br><a href="https://www.cloudflare.com/">https://www.cloudflare.com/</a></p>



<p>CloudFlare 主要是基於內容傳遞網路（Content Delivery Network, 簡稱 CDN）和分散式網域名稱解析服務（Distributed Domain Name Server）等技術，於世界各地分布超過三十個資料中心，當使用者連接到使用 CloudFlare 服務的網站後，會從最接近使用者的資料中心來接收網站內容，以加快網站載入速度。</p>



<p>CloudFlare 提供網站基本安全防護功能，將真實伺服器 IP 位址隱藏在 CF 伺服器後，避免伺服器被攻擊、入侵或對網站造成危害，加速以外更增添了安全性。</p>



<p>以上2點都是 CloudFlare 免費方案的功能，若你想得到更多的可自訂項目，或是增加連線的速度和安全防護效能，也可考慮付費來升級為 Pro 或 Business 等高級方案。</p>



<hr class="wp-block-separator"/>



<h2 class="wp-block-heading">移除不要的網域名稱</h2>



<p>某一個已經註冊好的domain想要移去別台機器的時候，指令如下：</p>



<pre class="wp-block-preformatted">certbot delete --cert-name your-domain.com</pre>



<p>上面的 your-domain.com 需要換成自己當初申請的 domain name, 如果忘記是什麼的話，可以到這一個目錄下查看：<code>/etc/letsencrypt/renewal</code></p>



<p>操作的畫面如下，可能會有二組，有www 和 沒有 www 的 .conf , 實際上到底申請了幾組，需要到 renewal 目錄下查看。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="660" height="215" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-06-at-16.26.51.jpg" alt="" class="wp-image-3726" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-06-at-16.26.51.jpg?v=1620289802 660w, https://stackoverflow.max-everyday.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-06-at-16.26.51-600x195.jpg?v=1620289802 600w" sizes="(max-width: 660px) 100vw, 660px" /></figure>



<hr class="wp-block-separator"/>



<h2 class="wp-block-heading">相關文章</h2>



<p>apache AH00171: Graceful restart requested, doing restart<br><a href="https://stackoverflow.max-everyday.com/2017/02/apache-graceful-restart/">https://stackoverflow.max-everyday.com/2017/02/apache-graceful-restart/</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2017/01/lets-encrypt-free-https/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
