<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mitch Jackson</title>
    <description>The latest articles on DEV Community by Mitch Jackson (@mjac).</description>
    <link>https://dev.to/mjac</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F64757%2Fa360303c-8745-4c09-8133-a59d16a1fbf7.jpg</url>
      <title>DEV Community: Mitch Jackson</title>
      <link>https://dev.to/mjac</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mjac"/>
    <language>en</language>
    <item>
      <title>csh - simple helper for urxvt</title>
      <dc:creator>Mitch Jackson</dc:creator>
      <pubDate>Mon, 04 May 2020 21:54:00 +0000</pubDate>
      <link>https://dev.to/mjac/csh-simple-helper-for-urxvt-1jdh</link>
      <guid>https://dev.to/mjac/csh-simple-helper-for-urxvt-1jdh</guid>
      <description>&lt;p&gt;This shell script provides quick SSH shortcuts, and displays a configurable terminal background color while connected.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;!/bin/csh&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# cssh: Color SSH helper&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# Author: Mitch Jackson &amp;lt;mitch@mitchjacksontech.com&lt;/span&gt;
&lt;span class="c"&gt;# Copyright: &lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# Set the terminal background color and transparency before&lt;/span&gt;
&lt;span class="c"&gt;# making an SSH connection, then resets them when the connection closes&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# Allows for configuring different background colors per host,&lt;/span&gt;
&lt;span class="c"&gt;# along with connetion aliases&lt;/span&gt;

&lt;span class="c"&gt;# background color and opacity value to use during the session&lt;/span&gt;
&lt;span class="nv"&gt;CONN_BGCOLOR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"#330000"&lt;/span&gt;
&lt;span class="nv"&gt;CONN_OPACITY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;85

&lt;span class="c"&gt;# background color and opacity to return to after the session ends&lt;/span&gt;
&lt;span class="nv"&gt;EXIT_BGCOLOR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"#000000"&lt;/span&gt;
&lt;span class="nv"&gt;EXIT_OPACITY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;70

&lt;span class="c"&gt;# Connection Definitions:&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# Define a shortname for each connection below&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="k"&gt;in
  &lt;/span&gt;box1&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;SSH_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"box1.lion.land"&lt;/span&gt;
    &lt;span class="p"&gt;;;&lt;/span&gt;
  box2&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;SSH_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"10.0.0.2"&lt;/span&gt;
    &lt;span class="nv"&gt;CONN_BGCOLOR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"#002200"&lt;/span&gt;
    &lt;span class="p"&gt;;;&lt;/span&gt;

  &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;# Catch-all&lt;/span&gt;
    &lt;span class="nv"&gt;SSH_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nv"&gt;CONN_BGCOLOR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"#000333"&lt;/span&gt;
    &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="k"&gt;esac&lt;/span&gt;

&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'\33]11;%s\007'&lt;/span&gt; &lt;span class="s2"&gt;"[&lt;/span&gt;&lt;span class="nv"&gt;$CONN_OPACITY&lt;/span&gt;&lt;span class="s2"&gt;]&lt;/span&gt;&lt;span class="nv"&gt;$CONN_BGCOLOR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;command &lt;/span&gt;ssh &lt;span class="nv"&gt;$SSH_HOST&lt;/span&gt; &lt;span class="nv"&gt;$2&lt;/span&gt; &lt;span class="nv"&gt;$3&lt;/span&gt; &lt;span class="nv"&gt;$4&lt;/span&gt;
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'\33]11;%s\007'&lt;/span&gt; &lt;span class="s2"&gt;"[&lt;/span&gt;&lt;span class="nv"&gt;$EXIT_OPACITY&lt;/span&gt;&lt;span class="s2"&gt;]&lt;/span&gt;&lt;span class="nv"&gt;$EXIT_BGCOLOR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, a simple script to set the terminal background color and opacity at any time&lt;/p&gt;

&lt;p&gt;&lt;code&gt;!/bin/tglow&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# tglow: Set terminal background and opacity&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# Author: Mitch Jackson &amp;lt;mitch@mitchjacksontech.com&lt;/span&gt;
&lt;span class="c"&gt;# Copyright: Nope&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;usage&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;echo
  echo&lt;/span&gt; &lt;span class="s2"&gt;"tglow: set terminal background and opacity"&lt;/span&gt;
  &lt;span class="nb"&gt;echo
  echo&lt;/span&gt; &lt;span class="s2"&gt;"    usage: tglow 30 green"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"           tglow 95 &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;#333000&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;echo
  exit &lt;/span&gt;1
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="p"&gt;+x&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;usage
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'\33]11;%s\007'&lt;/span&gt; &lt;span class="s2"&gt;"[&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;]&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frd0qy5cdznevm1xm3mlg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frd0qy5cdznevm1xm3mlg.png" alt="Alt Text" width="800" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>urxvt</category>
      <category>linux</category>
    </item>
    <item>
      <title>Perl 5.30 deprecates use of my() in a false conditional</title>
      <dc:creator>Mitch Jackson</dc:creator>
      <pubDate>Mon, 10 Jun 2019 18:08:23 +0000</pubDate>
      <link>https://dev.to/mjac/perl-5-30-deprecates-use-of-my-in-a-false-conditional-55bg</link>
      <guid>https://dev.to/mjac/perl-5-30-deprecates-use-of-my-in-a-false-conditional-55bg</guid>
      <description>&lt;p&gt;Perl 5.30.0 is released (&lt;a href="https://metacpan.org/pod/release/XSAWYERX/perl-5.30.0/pod/perldelta.pod" rel="noopener noreferrer"&gt;changelog&lt;/a&gt;).  With it comes a breaking change for me.  It has been a long time since I've faced a breaking change with perl.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://metacpan.org/pod/distribution/perl/pod/perldiag.pod#Deprecated-use-of-my()-in-false-conditional.-This-will-be-a-fatal-error-in-Perl-5.30" rel="noopener noreferrer"&gt;Deprecated use of my() in false conditional&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I have been using this deprecated syntax liberally like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# This syntax generates a fatal error in perl 5.30&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# Initialize $foo&lt;/span&gt;
&lt;span class="c1"&gt;#   If $bar tests true, $foo = 'foobar'&lt;/span&gt;
&lt;span class="c1"&gt;#   If $bar tests false, $foo = undef&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foobar&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$bar&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;There has been a long-standing bug in Perl that causes a lexical variable not to be cleared at scope exit when its declaration includes a false conditional.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This could make for interesting bugs.  The scoped variable declared this way may unexpectedly persist data!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Use this instead&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$foo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$bar&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;$foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foobar&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Or this&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$foo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foobar&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$bar&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;According to &lt;a href="https://rt.perl.org/Public/Bug/Display.html?id=133543#txn-1599917" rel="noopener noreferrer"&gt;RT# 133543&lt;/a&gt;, the deprecation will not always be triggered with this syntax!  Therefore, I feel I can't trust a run of a test suite under 5.30 to identify all the offending code statements.&lt;/p&gt;

&lt;p&gt;Is anybody else surprised to learn this declaration pattern is problematic?&lt;/p&gt;

</description>
      <category>perl</category>
      <category>deprecated</category>
    </item>
    <item>
      <title>How Do You Decide to Plunge Into a Startup?</title>
      <dc:creator>Mitch Jackson</dc:creator>
      <pubDate>Tue, 17 Jul 2018 06:13:53 +0000</pubDate>
      <link>https://dev.to/mjac/how-do-you-decide-to-plunge-into-a-startup-2njp</link>
      <guid>https://dev.to/mjac/how-do-you-decide-to-plunge-into-a-startup-2njp</guid>
      <description>&lt;p&gt;I'm confident in the product. What other factors should I consider before giving significant time and resources into a startup as a minority owner with a majority share of the software/hardware development?&lt;/p&gt;

&lt;p&gt;That familiar place we all arrive at as developers:  &lt;strong&gt;Let's make a business out of this!&lt;/strong&gt;  It is often an educational time sink.  You learn just how reliably yourself and your friends will work without pay to chase a dream.&lt;/p&gt;

&lt;p&gt;I'm facing this question again!  My friend, the CEO of a long-standing non-profit, made a software wish while we played board games on Thanksgiving.  &lt;strong&gt;Hold my beer...&lt;/strong&gt;  Several months later, as a volunteer, I've rewritten large parts of their infrastructure, built and integrated custom hardware deployments based on small board computers, and provided whiz-bang new features that were a first for their market.  There was much rejoicing.  I sacrificed into my day-job billable hours more than I want to admit to make this happen.&lt;/p&gt;

&lt;p&gt;Now somebody else in the same space wants the same capability, and they're shopping vendors.&lt;/p&gt;

&lt;p&gt;The product is not just a website.  There is hardware/software integration. Significant business integration. As well as live event support. Somebody would have to travel several countries supporting installations and providing training. That person would NOT be me.&lt;/p&gt;

&lt;p&gt;Everybody involved in the company would be working in "side-job" capacity.  There's not enough money in the beginning to support full time employees.&lt;/p&gt;

&lt;p&gt;What factors would YOU consider before deciding to join with such a company?  What steps would you make early, as the business is structured, to realize both success and a good financial position?&lt;/p&gt;

</description>
      <category>advice</category>
      <category>discuss</category>
      <category>business</category>
    </item>
    <item>
      <title>SMS Notifications with Perl and Twilio</title>
      <dc:creator>Mitch Jackson</dc:creator>
      <pubDate>Thu, 14 Jun 2018 06:11:39 +0000</pubDate>
      <link>https://dev.to/mjac/sms-notifications-with-perl-and-twilio-1lbi</link>
      <guid>https://dev.to/mjac/sms-notifications-with-perl-and-twilio-1lbi</guid>
      <description>&lt;p&gt;&lt;a href="https://twilio.com" rel="noopener noreferrer"&gt;Twilio&lt;/a&gt; is beyond useful, and easy to integrate.  It's one of those tools that, once you get started, you just can't stop using it.  You can add SMS Notifications and password resets to your existing application in an afternoon.&lt;/p&gt;

&lt;p&gt;I see several examples of Twilio usage on dev.to.  But of course, none for Perl, until now.&lt;/p&gt;

&lt;h2&gt;
  
  
  First, the entire simple program:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env perl&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;v5&lt;/span&gt;&lt;span class="mf"&gt;.10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;strict&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;warnings&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;LWP::&lt;/span&gt;&lt;span class="nv"&gt;UserAgent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;%text_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;From&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;12513001300&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="c1"&gt;# Me&lt;/span&gt;
    &lt;span class="s"&gt;To&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;16198675309&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="c1"&gt;# Jenny&lt;/span&gt;
    &lt;span class="s"&gt;Body&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Thank you for being a friend! Travel down the road and back again!&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;%credentials&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;account_id&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;____YOUR_ACCOUNT_SID_GOES_HERE____&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
    &lt;span class="s"&gt;auth_token&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;____YOUR_AUTH_TOKEN_GOES_HERE____&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;%twilio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;# HTTP Authentication&lt;/span&gt;
    &lt;span class="s"&gt;api_domain&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;api.twilio.com:443&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
    &lt;span class="s"&gt;api_realm&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Twilio API&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;

    &lt;span class="c1"&gt;# Keep your line length within 80 characters please!&lt;/span&gt;
    &lt;span class="s"&gt;api_url&lt;/span&gt;    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.twilio.com/2010-04-01/Accounts/&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;
                  &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$credentials&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;account_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                  &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/Messages&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$ua&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;LWP::&lt;/span&gt;&lt;span class="nv"&gt;UserAgent&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$ua&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;$twilio&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;api_domain&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nv"&gt;$twilio&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;api_realm&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nv"&gt;$credentials&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;account_id&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nv"&gt;$credentials&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;auth_token&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$ua&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$twilio&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;api_url&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="nv"&gt;%text_message&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;is_success&lt;/span&gt;
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Message delivered&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error: &lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;decoded_content&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  As this is a #beginner post, let's break this down statement by statement.
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env perl&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;v5&lt;/span&gt;&lt;span class="mf"&gt;.10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;strict&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;warnings&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Begin with a &lt;a href="https://en.wikipedia.org/wiki/Shebang_(Unix)" rel="noopener noreferrer"&gt;Shebang Line&lt;/a&gt;.  If you execute this program from a shell, this is how the shell knows which interpreter to use for the program.  &lt;code&gt;#!/usr/bin/env perl&lt;/code&gt; has replaced the long in the tooth standard &lt;code&gt;#!/usr/bin/perl&lt;/code&gt; with good reason.&lt;/p&gt;

&lt;p&gt;Invoking &lt;code&gt;use v5.10;&lt;/code&gt; here allows us to use the &lt;a href="https://perldoc.perl.org/functions/say.html" rel="noopener noreferrer"&gt;say&lt;/a&gt; function.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;use strict&lt;/code&gt; and &lt;code&gt;use warnings&lt;/code&gt; asks Perl to warn you if you're doing something stupid.  Like misspelling a variable name, or blogging at 2am.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;LWP::&lt;/span&gt;&lt;span class="nv"&gt;UserAgent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://metacpan.org/pod/LWP::UserAgent" rel="noopener noreferrer"&gt;LWP::UserAgent&lt;/a&gt; can perform most actions your web browser does.  You can use it to browse pages, click links, and POST forms.  It can keep persistent cookies.  If you wanted to, say, write a robot to cheat an online poll, look no further.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;%text_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;From&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;12513001300&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="c1"&gt;# Me&lt;/span&gt;
    &lt;span class="s"&gt;To&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;16198675309&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="c1"&gt;# Jenny&lt;/span&gt;
    &lt;span class="s"&gt;Body&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Thank you for being a friend! Travel down the road and back again!&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Store information about your text message into a hash. You'll want to replace the example data with your own.  Jenny's had enough phone harassment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;%credentials&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;account_id&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;____YOUR_ACCOUNT_SID_GOES_HERE____&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
    &lt;span class="s"&gt;auth_token&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;____YOUR_AUTH_TOKEN_GOES_HERE____&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can find your Twilio account credentials in the Dashboard under Settings/General.  Twilio offers test API access.  You can use the test API to text yourself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;%twilio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;# HTTP Authentication&lt;/span&gt;
    &lt;span class="s"&gt;api_domain&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;api.twilio.com:443&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
    &lt;span class="s"&gt;api_realm&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Twilio API&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;

    &lt;span class="c1"&gt;# Keep your line length within 80 characters please!&lt;/span&gt;
    &lt;span class="s"&gt;api_url&lt;/span&gt;    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.twilio.com/2010-04-01/Accounts/&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;
                  &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$credentials&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;account_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                  &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/Messages&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Information you need to send a request to the Twilio API.  Twilio uses &lt;a href="https://en.wikipedia.org/wiki/Basic_access_authentication" rel="noopener noreferrer"&gt;Basic HTTP Authentication&lt;/a&gt;.   Here is the DOMAIN and REALM for this authentication scheme.  The Twilio API URL contains your account SID, so the full API URL is concatenated here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$ua&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;LWP::&lt;/span&gt;&lt;span class="nv"&gt;UserAgent&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$ua&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;$twilio&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;api_domain&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nv"&gt;$twilio&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;api_realm&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nv"&gt;$credentials&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;account_id&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nv"&gt;$credentials&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;auth_token&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instantiate a new instance of the LWP::UserAgent object, and set the credentials it will use for the HTTP Request to the Twilio API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$ua&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$twilio&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;api_url&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="nv"&gt;%text_message&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;$ua makes a HTTP POST request to $twilio{api_url}.  The data from %text_message are sent as form values.  This operation returns a &lt;a href="https://metacpan.org/pod/HTTP::Response" rel="noopener noreferrer"&gt;HTTP::Response&lt;/a&gt; Object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;is_success&lt;/span&gt;
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Message delivered&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error: &lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;decoded_content&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This statement includes the &lt;a href="https://perldoc.perl.org/perlop.html" rel="noopener noreferrer"&gt;ternary operator&lt;/a&gt;, a short-hand for an if-else block.  (Side note:  If you didn't know what a ternary operator was, or what it was called, and you saw this statement block in some code, how would you phrase your internet search to learn what this statement was doing?  Let me know in the comments...)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$response-&amp;gt;is_success&lt;/code&gt; returns true or false based on the &lt;a href="https://en.wikipedia.org/wiki/List_of_HTTP_status_codes" rel="noopener noreferrer"&gt;HTTP Status Code&lt;/a&gt; returned by the web server.&lt;/p&gt;

&lt;p&gt;If Twilio reports the request was successful, you see &lt;strong&gt;Message Delivered&lt;/strong&gt; displayed in your terminal.  If Twilio reports a problem, you will see the full response from the Twilio API displayed in your terminal.&lt;/p&gt;

&lt;h2&gt;
  
  
  See how easy Twilio is?  Go build something...
&lt;/h2&gt;

&lt;p&gt;Frankly, Twilio has made themselves so easy to use that most languages can break their use down to one-liners.  You can easily deliver an SMS via the shell using curl.&lt;/p&gt;

&lt;p&gt;If you ever meet a Twilio engineer, be sure to buy them a beer.&lt;/p&gt;

&lt;p&gt;Are you still reading?  Go build something!&lt;/p&gt;

</description>
      <category>perl</category>
      <category>sms</category>
      <category>twilio</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Would you pay a data ransom?</title>
      <dc:creator>Mitch Jackson</dc:creator>
      <pubDate>Sun, 03 Jun 2018 20:58:26 +0000</pubDate>
      <link>https://dev.to/mjac/would-you-pay-a-data-ransom-3h5f</link>
      <guid>https://dev.to/mjac/would-you-pay-a-data-ransom-3h5f</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fselfb31pebihka8dmy09.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fselfb31pebihka8dmy09.jpg" alt="TMBG Ticket" width="800" height="959"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Ticketfly.com data breach
&lt;/h1&gt;

&lt;p&gt;I was notified by &lt;a href="https://haveibeenpwned.com" rel="noopener noreferrer"&gt;Have I Been Pwned&lt;/a&gt; that my Name, E-Mail address, Mailing addresses and phone numbers were dumped publicly online as part of the &lt;a href="http://ticketfly.com" rel="noopener noreferrer"&gt;ticketfly.com&lt;/a&gt; data ransom involving 26 million account records.  &lt;a href="https://www.billboard.com/articles/business/8458918/ticketfly-warned-hacker-vulnerability-website-down" rel="noopener noreferrer"&gt;Motherboard reports&lt;/a&gt; the attacker requested a ransom of 1BTC (~$7500).  It's unclear if the request was ignored intentionally, or overlooked.  In theory, it would have cost ticketfly.com $0.000288 to protect my customer record.  Now the dark web knows I always buy tickets to see They Might Be Giants.&lt;/p&gt;

&lt;h1&gt;
  
  
  Would I pay the 1BTC ransom?
&lt;/h1&gt;

&lt;p&gt;It's common advice that a blackmailer will never stop asking for more money.  It's also safe to assume that just because the hacker doesn't publicly dump the data immediately, she/he will still be selling it on the black market.&lt;/p&gt;

&lt;p&gt;However this is a low-cost ransom request.  Paying the ransom may buy time to fix the vulnerability, and perhaps could have kept ticketfly online.  I'm told that venues cannot buy, sell, or verify tickets for concerts this weekend.  This is going to cause probably more than $7500 in damage to every ticketfly venue.&lt;/p&gt;

&lt;p&gt;I'd would have paid the ransom.&lt;/p&gt;

&lt;p&gt;What would you do?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>ticketfly</category>
      <category>breach</category>
    </item>
    <item>
      <title>Auto-generate a Database Schema Diagram</title>
      <dc:creator>Mitch Jackson</dc:creator>
      <pubDate>Sat, 02 Jun 2018 03:34:14 +0000</pubDate>
      <link>https://dev.to/mitchjacksontech/auto-generate-a-database-schema-diagram-be3</link>
      <guid>https://dev.to/mitchjacksontech/auto-generate-a-database-schema-diagram-be3</guid>
      <description>

&lt;h1&gt;
  
  
  Generate a Live Database Schema Diagram for your Catalyst Application
&lt;/h1&gt;

&lt;p&gt;When building a web application, I always create a URL endpoint that generates a database schema diagram on the fly.  This is a quick reference item that never gets old.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kL3Hzgfq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/jum5zbmuj6c6612nfjza.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kL3Hzgfq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/jum5zbmuj6c6612nfjza.png" alt="schema diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This approach can be used with any Perl web framework.  The provided example is for the Catalyst Framework using a DBIx::Class ORM.  This example provides the url &lt;a href="http://mywebsite.com/dbdiagram"&gt;http://mywebsite.com/dbdiagram&lt;/a&gt;&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight perl"&gt;&lt;code&gt;
&lt;span class="cm"&gt;=head2 dbdiagram

Render an image representing the current data model

=cut&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;SQL::&lt;/span&gt;&lt;span class="nv"&gt;Translator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;dbdiagram&lt;/span&gt; &lt;span class="p"&gt;:Local :Args(0) {&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;@_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$translator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;SQL::&lt;/span&gt;&lt;span class="nv"&gt;Translator&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nv"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;'SQL::Translator::Parser::DBIx::Class'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nv"&gt;data&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$c&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Ezn'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nv"&gt;producer&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;'Diagram'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nv"&gt;producer_args&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;output_type&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;'png'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nv"&gt;title&lt;/span&gt;       &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"My clever database diagram"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nv"&gt;add_color&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nv"&gt;font_size&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;'large'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="nb"&gt;die&lt;/span&gt; &lt;span class="nn"&gt;SQL::&lt;/span&gt;&lt;span class="nv"&gt;Translator&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nv"&gt;$c&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;res&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;content_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'image/png'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$c&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;res&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$translator&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Don't Forget&lt;/em&gt; to restrict to authorized users!&lt;/p&gt;

&lt;p&gt;See also: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.catalystframework.org/"&gt;Catalyst Framework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://metacpan.org/pod/DBIx::Class"&gt;DBIx::Class&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://metacpan.org/pod/SQL::Translator::Parser::DBIx::Class"&gt;SQL::Translator::Parser::DBIx::Class&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://metacpan.org/pod/SQL::Translator::Producer::Diagram"&gt;SQL::Translator::Producer::Diagram&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


</description>
      <category>perl</category>
      <category>catalyst</category>
      <category>dbixclass</category>
      <category>howto</category>
    </item>
    <item>
      <title>Trac Install Guide</title>
      <dc:creator>Mitch Jackson</dc:creator>
      <pubDate>Fri, 25 May 2018 03:06:19 +0000</pubDate>
      <link>https://dev.to/mjac/trac-install-guide-588e</link>
      <guid>https://dev.to/mjac/trac-install-guide-588e</guid>
      <description>&lt;h1&gt;
  
  
  Install Trac with Git on a Debian 9
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmrskgwy0jmyobefco3cp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmrskgwy0jmyobefco3cp.png" alt="Trac" width="450" height="511"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since I was documenting the process anyway, why not make my first post with dev.to a software install guide.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trac is my favored project management environment
&lt;/h2&gt;

&lt;p&gt;Trac has been around for a long time.  I was using it before git existed.  It's been stable and reliable all this time.  Unlike all the big bloated tools out there these days like GitLab and Jira, Trac runs quite well on the cheapest virtual servers you can rent.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Features include:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Ticketing system&lt;/li&gt;
&lt;li&gt;Milestone tracking&lt;/li&gt;
&lt;li&gt;Time tracking&lt;/li&gt;
&lt;li&gt;Git integration with repository browsing&lt;/li&gt;
&lt;li&gt;Wiki&lt;/li&gt;
&lt;li&gt;Automated notifications&lt;/li&gt;
&lt;li&gt;CI integration&lt;/li&gt;
&lt;li&gt;Low system requirements&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  About this guide
&lt;/h2&gt;

&lt;p&gt;Most guides or walkthroughs of this sort are very basic.  They try to get you there with the least amount of information possible.  My approach to guides opposes this philosophy.  Advanced users may choose to skip over extra information like firewall configuration, and setting up E-Mail forwarding.&lt;/p&gt;

&lt;p&gt;It's assumed the shell commands presented will be run using sudo, or as root.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prepare your server
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Create a Digital Ocean droplet using Debian 9
&lt;/h3&gt;

&lt;p&gt;Creating a server with Digital Ocean is quite straightforward.  Trac can run comfortably on the $5/mo small DO droplet.  &lt;a href="https://m.do.co/c/5745ded1be6a" rel="noopener noreferrer"&gt;Use my referral link&lt;/a&gt; and get $10 of free credit.&lt;/p&gt;

&lt;p&gt;This guide was written using Digital Ocean.  You may encounter very minor differences during install in another environment.  However this guide should still get you there.  If not, please let me know.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure DNS for your Trac server
&lt;/h3&gt;

&lt;p&gt;An obvious candidate is trac.yourdomain.com.  This uses that example domain name.  Update DNS so your new domain name points to your server. &lt;/p&gt;

&lt;p&gt;You will also need an SPF record, or most mail your server sends will be rejected as spam.  This will probably be adequate for your use case:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;TXT @ v=spf1 a -all&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Update the server
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aptitude &lt;span class="nt"&gt;-y&lt;/span&gt; update
aptitude &lt;span class="nt"&gt;-y&lt;/span&gt; upgrade
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configure hostname  and domain name on your server
&lt;/h3&gt;

&lt;p&gt;Override Digital Ocean auto-config of domain name&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/^manage_etc_hosts: true$/manage_etc_hosts: False/'&lt;/span&gt; /etc/cloud/cloud.cfg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set the system hostname&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt; &amp;gt; /etc/hostname
trac
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit &lt;code&gt;/etc/hosts&lt;/code&gt; to set the system domain name&lt;/p&gt;

&lt;p&gt;Find these lines&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="m"&gt;127&lt;/span&gt;.&lt;span class="m"&gt;0&lt;/span&gt;.&lt;span class="m"&gt;1&lt;/span&gt;.&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt;.&lt;span class="n"&gt;com&lt;/span&gt; &lt;span class="n"&gt;droplet&lt;/span&gt;
&lt;span class="m"&gt;127&lt;/span&gt;.&lt;span class="m"&gt;0&lt;/span&gt;.&lt;span class="m"&gt;1&lt;/span&gt;.&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="n"&gt;localhost&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update for your trac domain name&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="m"&gt;127&lt;/span&gt;.&lt;span class="m"&gt;0&lt;/span&gt;.&lt;span class="m"&gt;1&lt;/span&gt;.&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="n"&gt;trac&lt;/span&gt;.&lt;span class="n"&gt;yourdomain&lt;/span&gt;.&lt;span class="n"&gt;com&lt;/span&gt; &lt;span class="n"&gt;trac&lt;/span&gt;
&lt;span class="m"&gt;127&lt;/span&gt;.&lt;span class="m"&gt;0&lt;/span&gt;.&lt;span class="m"&gt;0&lt;/span&gt;.&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="n"&gt;localhost&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Do not&lt;/em&gt; use simply use your root domain, yourdomain.com.  You must have a subdomain prepended, such as trac.yourdomain.com.  Otherwise you will have trouble later in the guide, allowing Trac to send e-mail notifications&lt;/p&gt;

&lt;p&gt;At this point, reboot your server, and confirm your domain name and hostname remain correct after reboots.  Use the shell commands &lt;code&gt;hostname&lt;/code&gt; and &lt;code&gt;domainname&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure the firewall
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Install and enable firewalld
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aptitude &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nb"&gt;install &lt;/span&gt;firewalld
systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;firewalld
systemctl start firewalld
firewall-cmd &lt;span class="nt"&gt;--zone&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;public &lt;span class="nt"&gt;--add-interface&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;eth0
firewall-cmd &lt;span class="nt"&gt;--zone&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;public &lt;span class="nt"&gt;--add-interface&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;eth0 &lt;span class="nt"&gt;--permanent&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Protecting SSH
&lt;/h4&gt;

&lt;p&gt;Many people will advise you to jump through hoops to protect SSH on your linux server.  Unless you really need SSH available to the whole world (you don't) use my simpler approach.  Disallow SSH in your firewall, except for trusted ip addresses.  Since the whole internet can't talk to your SSH port, there's no need for elaborate settings and blocking firewalls like fail2ban.&lt;/p&gt;

&lt;p&gt;Repeat the following commands for every trusted IP address&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Repeat these commands for every trusted IP address&lt;/span&gt;
firewall-cmd &lt;span class="nt"&gt;--zone&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;trusted &lt;span class="nt"&gt;--add-source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.2.3.4
firewall-cmd &lt;span class="nt"&gt;--zone&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;trusted &lt;span class="nt"&gt;--add-source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.2.3.4 &lt;span class="nt"&gt;--permanent&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Should you find yourself unable to connect to SSH, because your current IP address has not been added to the trusted list, this is no problem.  Just visit your server dashboard at digitalocean.com.   Select the Access menu item.  You will see a big blue button that says Launch Console.  This gives you shell access to your server over the web.  Issue the above command to grant yourself access from your new IP address. &lt;/p&gt;

&lt;p&gt;Disable SSH to the public internet&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;firewall-cmd &lt;span class="nt"&gt;--zone&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;public &lt;span class="nt"&gt;--remove-service&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ssh
firewall-cmd &lt;span class="nt"&gt;--zone&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;public &lt;span class="nt"&gt;--remove-service&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ssh &lt;span class="nt"&gt;--permanent&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Allow websites hosted on your server through your firewall&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;firewall-cmd &lt;span class="nt"&gt;--zone&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;public &lt;span class="nt"&gt;--add-service&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http
firewall-cmd &lt;span class="nt"&gt;--zone&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;public &lt;span class="nt"&gt;--add-service&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http &lt;span class="nt"&gt;--permanent&lt;/span&gt;
firewall-cmd &lt;span class="nt"&gt;--zone&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;public &lt;span class="nt"&gt;--add-service&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https
firewall-cmd &lt;span class="nt"&gt;--zone&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;public &lt;span class="nt"&gt;--add-service&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https &lt;span class="nt"&gt;--permanent&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Get a free SSL certificate free from Lets Encrypt
&lt;/h3&gt;

&lt;p&gt;You want all interactions with Trac and Git to be secure.  To do this, enforce https for all your web traffic.  You will need a security certificate for this.  &lt;/p&gt;

&lt;h4&gt;
  
  
  Your DNS records must be in place for this step
&lt;/h4&gt;

&lt;p&gt;Depending on your domain registry, and how you manage your DNS records, it can take minutes to hours before your new DNS names appear to everybody on the internet.  If you cannot ping your domain name (&lt;code&gt;ping trac.yourdomain.com&lt;/code&gt;) you will need to wait a while before completing this step.&lt;/p&gt;

&lt;h4&gt;
  
  
  Use certbot to request an SSL certificate
&lt;/h4&gt;

&lt;p&gt;Install certbot&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aptitude &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nb"&gt;install &lt;/span&gt;certbot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Stop your web server, if it's running.  Certbot will prove you own this domain name by hosting it's own temporary web server.  There are other ways to use certbot.  Look at letsencrypt.org if you're interested.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl stop apache2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Request an SSL certificate.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;certbot certonly &lt;span class="nt"&gt;--standalone&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;--agree-tos&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-m&lt;/span&gt; youremail@yourdomain.com &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-d&lt;/span&gt; trac.yourdomain.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will configure the server to use this certificate later.  The certificate can be found at:&lt;br&gt;
 &lt;code&gt;/etc/letsencrypt/live/trac.mydomain.com/*.pem&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Configure a local mail server so Trac can send E-Mails
&lt;/h3&gt;

&lt;p&gt;Install Exim&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aptitude &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nb"&gt;install &lt;/span&gt;exim4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update the Exim config file to contain these directives:&lt;br&gt;
&lt;code&gt;/etc/exim4/update-exim4.conf.conf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;dc_eximconfig_configtype&lt;/span&gt;=&lt;span class="s1"&gt;'internet'&lt;/span&gt;
&lt;span class="n"&gt;dc_eximconfig_other_hostnames&lt;/span&gt;=&lt;span class="s1"&gt;'trac.yourdomain.com'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do not specify yourdomain.com as dc_eximconfig_other_hostnames, or mail to @yourdomain.com addresses will never be delivered.  Also, if the output of the &lt;code&gt;domainname&lt;/code&gt; command is yourdomain.com instead of trac.yourdomain.com, mail to @yourdomain.com will never be delivered.  This happens because exim will try to deliver the mail locally, instead of over the internet.&lt;/p&gt;

&lt;p&gt;It's a good idea to create a root email alias on your server, so you receive notices from your server&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt; &amp;gt;&amp;gt; /etc/aliases
root: youremail@yourdomain.com
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart Exim to apply the changed configuration&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl restart exim4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check that Exim correctly decides to send mail via the internet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;exim &lt;span class="nt"&gt;-bt&lt;/span&gt; yourname@yourdomain.com
exim &lt;span class="nt"&gt;-bt&lt;/span&gt; yourname
exim &lt;span class="nt"&gt;-bt&lt;/span&gt; root
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Send a test e-mail&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Test email"&lt;/span&gt; | mail &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"testing new server"&lt;/span&gt; yourname@yourdomain.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Watch your logs if there is a problem&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /var/log/exim4/&lt;span class="k"&gt;*&lt;/span&gt; &amp;amp;
&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /var/log/maillog &amp;amp;
journalctl &lt;span class="nt"&gt;-f&lt;/span&gt; &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Install software and dependencies
&lt;/h2&gt;

&lt;p&gt;Install software via Debian packages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aptitude &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  apache2 &lt;span class="se"&gt;\&lt;/span&gt;
  exim4 &lt;span class="se"&gt;\&lt;/span&gt;
  git &lt;span class="se"&gt;\&lt;/span&gt;
  libapache2-mod-wsgi &lt;span class="se"&gt;\&lt;/span&gt;
  libmariadb-dev-compat &lt;span class="se"&gt;\&lt;/span&gt;
  mariadb-server &lt;span class="se"&gt;\&lt;/span&gt;
  python &lt;span class="se"&gt;\&lt;/span&gt;
  python-pip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the moment, Trac does not install properly for me using only debian packages.  You'll use a python virtual environment to install the latest version of Trac and associated libraries&lt;/p&gt;

&lt;p&gt;Create the project home&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/www/trac
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Spawn a virtual environment&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;virtualenv
virtualenv /var/www/trac/virtualenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Activate the virtual environment&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source&lt;/span&gt; /var/www/trac/virtualenv/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install Trac and dependencies&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;trac
pip &lt;span class="nb"&gt;install &lt;/span&gt;docutils
pip &lt;span class="nb"&gt;install &lt;/span&gt;babel
pip &lt;span class="nb"&gt;install &lt;/span&gt;pygments
pip &lt;span class="nb"&gt;install &lt;/span&gt;MySQL-python
pip &lt;span class="nb"&gt;install &lt;/span&gt;TracAccountManager
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setup MariaDB
&lt;/h2&gt;

&lt;p&gt;Enable MariaDB&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;mariadb
systemctl start mariadb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the following command and answer the questions.  You will set your database admin password here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mysql_secure_installation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a database for Trac, with the following SQL statements at the database prompt.  Of course, replace TRAC_DB_PASSWORD with a real password.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;mysql&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;trac&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="nb"&gt;CHARACTER&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;utf8&lt;/span&gt; &lt;span class="k"&gt;COLLATE&lt;/span&gt; &lt;span class="n"&gt;utf8_bin&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;ALL&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;trac&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="n"&gt;trac_db&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;localhost&lt;/span&gt; &lt;span class="n"&gt;IDENTIFIED&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="s1"&gt;'TRAC_DB_PASSWORD'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;FLUSH&lt;/span&gt; &lt;span class="k"&gt;PRIVILEGES&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Press&lt;/span&gt; &lt;span class="n"&gt;CTRL&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="n"&gt;exit&lt;/span&gt; &lt;span class="k"&gt;database&lt;/span&gt; &lt;span class="n"&gt;shell&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create a bare Git repository
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/www/trac/git
git init &lt;span class="nt"&gt;--bare&lt;/span&gt; /var/www/trac/git/myproject.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Trac Set-up
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Initialize a Trac project
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Initalize a trac project&lt;/span&gt;
trac-admin &lt;span class="se"&gt;\&lt;/span&gt;
  /var/www/trac/project &lt;span class="se"&gt;\&lt;/span&gt;
  initenv project &lt;span class="se"&gt;\&lt;/span&gt;
  mysql://trac_db:TRAC_DB_PASSWORD@localhost/trac &lt;span class="se"&gt;\&lt;/span&gt;
  git /var/www/trac/git/myproject.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Update Trac.ini
&lt;/h3&gt;

&lt;p&gt;Make the following changes to the Trac project config file&lt;br&gt;
&lt;code&gt;/var/www/trac/project/conf/trac.ini&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Add the following sections&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[components]&lt;/span&gt;
&lt;span class="err"&gt;tracopt.versioncontrol.git*&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="err"&gt;enabled&lt;/span&gt;
&lt;span class="py"&gt;tracopt.versioncontrol.git.git_fs.csetpropertyrenderer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;enabled&lt;/span&gt;
&lt;span class="py"&gt;tracopt.versioncontrol.git.git_fs.gitconnector&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;enabled&lt;/span&gt;
&lt;span class="py"&gt;tracopt.versioncontrol.git.git_fs.gitwebprojectsrepositoryprovider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;enabled&lt;/span&gt;
&lt;span class="err"&gt;acct_mgr.admin.*&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="err"&gt;enabled&lt;/span&gt;
&lt;span class="err"&gt;acct_mgr.api.*&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="err"&gt;enabled&lt;/span&gt;
&lt;span class="py"&gt;acct_mgr.db.sessionstore&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;disabled&lt;/span&gt;
&lt;span class="py"&gt;acct_mgr.htfile.htdigeststore&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;disabled&lt;/span&gt;
&lt;span class="py"&gt;acct_mgr.htfile.htpasswdstore&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;enabled&lt;/span&gt;
&lt;span class="err"&gt;acct_mgr.http.*&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="err"&gt;disabled&lt;/span&gt;
&lt;span class="err"&gt;acct_mgr.notification.*&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="err"&gt;enabled&lt;/span&gt;
&lt;span class="err"&gt;acct_mgr.pwhash.*&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="err"&gt;disabled&lt;/span&gt;
&lt;span class="err"&gt;acctmgr.register.*&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="err"&gt;enabled&lt;/span&gt;
&lt;span class="py"&gt;acct_mgr.svnserve.svnservepasswordstore&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;disabled&lt;/span&gt;
&lt;span class="err"&gt;acct_mgr.web_ui.*&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="err"&gt;enabled&lt;/span&gt;
&lt;span class="py"&gt;acct_mgr.web_ui.LoginModule&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;enabled&lt;/span&gt;
&lt;span class="py"&gt;acct_mgr.web_ui.resetpwstore&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;disabled&lt;/span&gt;
&lt;span class="py"&gt;acct_mgr.guard.accountguard&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;enabled&lt;/span&gt;
&lt;span class="py"&gt;trac.web.auth.LoginModule&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;disabled&lt;/span&gt;

&lt;span class="nn"&gt;[account-manager]&lt;/span&gt;
&lt;span class="py"&gt;password_store&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;HtPasswdStore&lt;/span&gt;
&lt;span class="py"&gt;htpasswd_hash_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;md5&lt;/span&gt;
&lt;span class="py"&gt;htpasswd_file&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/var/www/trac/users.htpasswd&lt;/span&gt;
&lt;span class="py"&gt;allow_delete_account&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;false&lt;/span&gt;
&lt;span class="py"&gt;login_attempt_max_count&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;5&lt;/span&gt;
&lt;span class="py"&gt;user_lock_time&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;60&lt;/span&gt;
&lt;span class="py"&gt;user_lock_max_time&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;0&lt;/span&gt;
&lt;span class="py"&gt;user_lock_time_progression&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;2&lt;/span&gt;



&lt;span class="nn"&gt;[git]&lt;/span&gt;
&lt;span class="py"&gt;shortrev_len&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;40&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit the logo section&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[header_logo]&lt;/span&gt;
&lt;span class="py"&gt;alt&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;Yet Another Trac Project&lt;/span&gt;
&lt;span class="py"&gt;height&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;-1&lt;/span&gt;
&lt;span class="py"&gt;link&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;
&lt;span class="py"&gt;src&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/chrome/common/trac_banner.png&lt;/span&gt;
&lt;span class="py"&gt;width&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;-1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit the attachment size limits&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[attachment]&lt;/span&gt;
&lt;span class="py"&gt;max_size&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;8388608&lt;/span&gt;
&lt;span class="py"&gt;max_zip_size&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;8388608&lt;/span&gt;
&lt;span class="py"&gt;render_unsafe_content&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;disabled&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit log settings, to log through syslog&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[logging]&lt;/span&gt;
&lt;span class="c"&gt;# log_file = trac.log
# log_format = &amp;lt;inherited&amp;gt;
&lt;/span&gt;&lt;span class="py"&gt;log_level&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;WARNING&lt;/span&gt;
&lt;span class="py"&gt;log_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;syslog&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit your project settings&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[project]&lt;/span&gt;
&lt;span class="py"&gt;admin&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;youremail@yourdomain.com&lt;/span&gt;
&lt;span class="py"&gt;admin_trac_url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;trac.yourdomain.com&lt;/span&gt;
&lt;span class="py"&gt;descr&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;Name For Your Project&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit the mail settings to use system sendmail for e-mail delivery.  Note, you can also instruct Trac to relay via SMTP if you prefer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[notification]&lt;/span&gt;
&lt;span class="py"&gt;email_sender&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;SendmailEmailSender&lt;/span&gt;
&lt;span class="py"&gt;smtp_from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;trac@yourdomain.com&lt;/span&gt;
&lt;span class="py"&gt;smtp_reply_to&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;trac@yourdomain.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create an empty password file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; /var/www/trac/users.htpasswd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Generate static files, python cache
&lt;/h3&gt;

&lt;p&gt;To reduce overhead in trac, extract and store static files that can be served directly by Apache.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/www/trac/static
trac-admin /var/www/trac/project deploy /var/www/trac/static
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Allow for a python code cache&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/www/trac/python_egg_cache
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configure Apache to serve Trac via WSGI
&lt;/h2&gt;

&lt;p&gt;Enable apache modules&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;a2enmod ssl
a2enmod wsgi
a2enmod cgi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set ownership of trac files to the apache system user&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chown &lt;/span&gt;www-data:www-data &lt;span class="nt"&gt;-R&lt;/span&gt; /var/www/trac
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit the apache config file.  If your server is going to host multiple websites, you may wish to create a new conf file, rather than editing the default one. &lt;br&gt;
&lt;code&gt;/etc/apache2/sites-available/000-default.conf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;
&amp;lt;&lt;span class="n"&gt;VirtualHost&lt;/span&gt; *:&lt;span class="m"&gt;80&lt;/span&gt;&amp;gt;
  &lt;span class="c"&gt;# Catch all non-ssl requests and redirect them to ssl
&lt;/span&gt;  &lt;span class="n"&gt;ServerName&lt;/span&gt; &lt;span class="n"&gt;trac&lt;/span&gt;.&lt;span class="n"&gt;yourdomain&lt;/span&gt;.&lt;span class="n"&gt;com&lt;/span&gt;
  &lt;span class="n"&gt;Redirect&lt;/span&gt; &lt;span class="n"&gt;permanent&lt;/span&gt; / &lt;span class="n"&gt;https&lt;/span&gt;://&lt;span class="n"&gt;trac&lt;/span&gt;.&lt;span class="n"&gt;yourdomain&lt;/span&gt;.&lt;span class="n"&gt;com&lt;/span&gt;/
&amp;lt;/&lt;span class="n"&gt;VirtualHost&lt;/span&gt;&amp;gt;

&amp;lt;&lt;span class="n"&gt;VirtualHost&lt;/span&gt; *:&lt;span class="m"&gt;443&lt;/span&gt;&amp;gt;
  &lt;span class="n"&gt;ServerName&lt;/span&gt; &lt;span class="n"&gt;trac&lt;/span&gt;.&lt;span class="n"&gt;yourdomain&lt;/span&gt;.&lt;span class="n"&gt;com&lt;/span&gt;

  &amp;lt;&lt;span class="n"&gt;IfModule&lt;/span&gt; &lt;span class="n"&gt;mod_headers&lt;/span&gt;.&lt;span class="n"&gt;c&lt;/span&gt;&amp;gt;
    &lt;span class="n"&gt;Header&lt;/span&gt; &lt;span class="n"&gt;always&lt;/span&gt; &lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="n"&gt;Strict&lt;/span&gt;-&lt;span class="n"&gt;Transport&lt;/span&gt;-&lt;span class="n"&gt;Security&lt;/span&gt; &lt;span class="s2"&gt;"max-age=15768000; includeSubDomains; preload"&lt;/span&gt;
  &amp;lt;/&lt;span class="n"&gt;IfModule&lt;/span&gt;&amp;gt;

  &lt;span class="n"&gt;CustomLog&lt;/span&gt; /&lt;span class="n"&gt;var&lt;/span&gt;/&lt;span class="n"&gt;log&lt;/span&gt;/&lt;span class="n"&gt;httpd&lt;/span&gt;/&lt;span class="n"&gt;yourdomain&lt;/span&gt;.&lt;span class="n"&gt;com_trac&lt;/span&gt;.&lt;span class="n"&gt;access&lt;/span&gt;.&lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="n"&gt;combined&lt;/span&gt;
  &lt;span class="n"&gt;ErrorLog&lt;/span&gt;  /&lt;span class="n"&gt;var&lt;/span&gt;/&lt;span class="n"&gt;log&lt;/span&gt;/&lt;span class="n"&gt;httpd&lt;/span&gt;/&lt;span class="n"&gt;yourdomain&lt;/span&gt;.&lt;span class="n"&gt;com_trac&lt;/span&gt;.&lt;span class="n"&gt;error&lt;/span&gt;.&lt;span class="n"&gt;log&lt;/span&gt;

  &lt;span class="n"&gt;SetEnv&lt;/span&gt; &lt;span class="n"&gt;PYTHON_EGG_CACHE&lt;/span&gt; /&lt;span class="n"&gt;var&lt;/span&gt;/&lt;span class="n"&gt;www&lt;/span&gt;/&lt;span class="n"&gt;trac&lt;/span&gt;/&lt;span class="n"&gt;python_egg_cache&lt;/span&gt;

  &lt;span class="n"&gt;Alias&lt;/span&gt; /&lt;span class="n"&gt;chrome&lt;/span&gt; /&lt;span class="n"&gt;var&lt;/span&gt;/&lt;span class="n"&gt;www&lt;/span&gt;/&lt;span class="n"&gt;trac&lt;/span&gt;/&lt;span class="n"&gt;static&lt;/span&gt;/&lt;span class="n"&gt;htdocs&lt;/span&gt;
  &amp;lt;&lt;span class="n"&gt;Directory&lt;/span&gt; &lt;span class="s2"&gt;"/var/www/trac/static/htdocs"&lt;/span&gt;&amp;gt;
    &amp;lt;&lt;span class="n"&gt;IfModule&lt;/span&gt; &lt;span class="n"&gt;mod_authz_core&lt;/span&gt;.&lt;span class="n"&gt;c&lt;/span&gt;&amp;gt;
      &lt;span class="n"&gt;Require&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="n"&gt;granted&lt;/span&gt;
    &amp;lt;/&lt;span class="n"&gt;IfModule&lt;/span&gt;&amp;gt;
  &amp;lt;/&lt;span class="n"&gt;Directory&lt;/span&gt;&amp;gt;

  &lt;span class="n"&gt;WSGIDaemonProcess&lt;/span&gt; &lt;span class="n"&gt;tracweb&lt;/span&gt; &lt;span class="n"&gt;python&lt;/span&gt;-&lt;span class="n"&gt;home&lt;/span&gt;=/&lt;span class="n"&gt;var&lt;/span&gt;/&lt;span class="n"&gt;www&lt;/span&gt;/&lt;span class="n"&gt;trac&lt;/span&gt;/&lt;span class="n"&gt;virtualenv&lt;/span&gt;
  &lt;span class="n"&gt;WSGIProcessGroup&lt;/span&gt; &lt;span class="n"&gt;tracweb&lt;/span&gt;
  &lt;span class="n"&gt;WSGIApplicationGroup&lt;/span&gt; %{&lt;span class="n"&gt;GLOBAL&lt;/span&gt;}
  &lt;span class="n"&gt;WSGIScriptAlias&lt;/span&gt; / /&lt;span class="n"&gt;var&lt;/span&gt;/&lt;span class="n"&gt;www&lt;/span&gt;/&lt;span class="n"&gt;trac&lt;/span&gt;/&lt;span class="n"&gt;static&lt;/span&gt;/&lt;span class="n"&gt;cgi&lt;/span&gt;-&lt;span class="n"&gt;bin&lt;/span&gt;/&lt;span class="n"&gt;trac&lt;/span&gt;.&lt;span class="n"&gt;wsgi&lt;/span&gt;
  &amp;lt;&lt;span class="n"&gt;Directory&lt;/span&gt; /&lt;span class="n"&gt;var&lt;/span&gt;/&lt;span class="n"&gt;www&lt;/span&gt;/&lt;span class="n"&gt;trac&lt;/span&gt;/&lt;span class="n"&gt;static&lt;/span&gt;/&lt;span class="n"&gt;cgi&lt;/span&gt;-&lt;span class="n"&gt;bin&lt;/span&gt;&amp;gt;
      &amp;lt;&lt;span class="n"&gt;IfModule&lt;/span&gt; &lt;span class="n"&gt;mod_authz_core&lt;/span&gt;.&lt;span class="n"&gt;c&lt;/span&gt;&amp;gt;
          &lt;span class="n"&gt;Require&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="n"&gt;granted&lt;/span&gt;
      &amp;lt;/&lt;span class="n"&gt;IfModule&lt;/span&gt;&amp;gt;
  &amp;lt;/&lt;span class="n"&gt;Directory&lt;/span&gt;&amp;gt;

  &lt;span class="n"&gt;SSLEngine&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt;
  &lt;span class="n"&gt;SSLCertificateFile&lt;/span&gt;    /&lt;span class="n"&gt;etc&lt;/span&gt;/&lt;span class="n"&gt;letsencrypt&lt;/span&gt;/&lt;span class="n"&gt;live&lt;/span&gt;/&lt;span class="n"&gt;www&lt;/span&gt;.&lt;span class="n"&gt;yourdomain&lt;/span&gt;.&lt;span class="n"&gt;com&lt;/span&gt;/&lt;span class="n"&gt;cert&lt;/span&gt;.&lt;span class="n"&gt;pem&lt;/span&gt;
  &lt;span class="n"&gt;SSLCertificateKeyFile&lt;/span&gt; /&lt;span class="n"&gt;etc&lt;/span&gt;/&lt;span class="n"&gt;letsencrypt&lt;/span&gt;/&lt;span class="n"&gt;live&lt;/span&gt;/&lt;span class="n"&gt;www&lt;/span&gt;.&lt;span class="n"&gt;yourdomain&lt;/span&gt;.&lt;span class="n"&gt;com&lt;/span&gt;/&lt;span class="n"&gt;privkey&lt;/span&gt;.&lt;span class="n"&gt;pem&lt;/span&gt;
  &lt;span class="n"&gt;SSLCertificateChainFile&lt;/span&gt; /&lt;span class="n"&gt;etc&lt;/span&gt;/&lt;span class="n"&gt;letsencrypt&lt;/span&gt;/&lt;span class="n"&gt;live&lt;/span&gt;/&lt;span class="n"&gt;www&lt;/span&gt;.&lt;span class="n"&gt;yourdomain&lt;/span&gt;.&lt;span class="n"&gt;com&lt;/span&gt;/&lt;span class="n"&gt;fullchain&lt;/span&gt;.&lt;span class="n"&gt;pem&lt;/span&gt;
&amp;lt;/&lt;span class="n"&gt;VirtualHost&lt;/span&gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check your Apache configuration for errors&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source&lt;/span&gt; /etc/apache2/envvars
apache2 &lt;span class="nt"&gt;-t&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Watch the output of your logs, to detect any problems&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;journalctl &lt;span class="nt"&gt;-f&lt;/span&gt; &amp;amp;
&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /var/log/apache2/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start Apache web server&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl restart apache2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Log in and configure Trac
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Authentication plugin
&lt;/h3&gt;

&lt;p&gt;Open trac.yourdomain.com in your browser.  If you've done everything correctly, you should see the introductory WIKI page.  Click the Login link, to be taken to the initial authentication setup&lt;/p&gt;

&lt;p&gt;Step 1: Choose the following options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Convert login names to lower case on registration and login - Checked&lt;/li&gt;
&lt;li&gt;Restrict sending cookies to HTTPS connections - Checked&lt;/li&gt;
&lt;li&gt;Authentication Front-End: Use a HTML login form&lt;/li&gt;
&lt;li&gt;Integrate links to related actions in the login form - Checked&lt;/li&gt;
&lt;li&gt;Allow the user to be remembered across sessions: checked&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Steps 2 through 5: No changes to defaults&lt;/p&gt;

&lt;p&gt;Step 6, choose your initial login name and password&lt;/p&gt;

&lt;h3&gt;
  
  
  Anonymous user permissions
&lt;/h3&gt;

&lt;p&gt;By default, website visitors can see basically everything.  In the admin menu, you can configure permissions for anonymous users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started with your Git repository
&lt;/h2&gt;

&lt;p&gt;From your workstation, not the server, clone the repository&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://trac.yourdomain.com/git/myproject.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a README.md file, commit to git, and push back to the server&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;myproject

&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt; &amp;gt; README.md
# My Project
I am just getting started with my project!
&lt;/span&gt;&lt;span class="no"&gt;EOF

&lt;/span&gt;git add README.md
git commit &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Add Readme File"&lt;/span&gt;
git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Visit Trac in your browser.  You should see the code changes reflected in the Timeline, and Browse Source menu options.&lt;/p&gt;

&lt;h1&gt;
  
  
  Troubleshooting
&lt;/h1&gt;

&lt;p&gt;Log files are your friends when something goes wrong on your server.   You can watch all the relevant logs in real time, to see what errors are given with something doesn't work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="c"&gt;# Linux system logs&lt;/span&gt;
journalctl &lt;span class="nt"&gt;-f&lt;/span&gt; &amp;amp;

&lt;span class="c"&gt;# E-Mail logs&lt;/span&gt;
&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /var/log/maillog &amp;amp;
&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /var/log/exim4/&lt;span class="k"&gt;*&lt;/span&gt; &amp;amp;

&lt;span class="c"&gt;# Web server logs&lt;/span&gt;
&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /var/log/apache2/&lt;span class="k"&gt;*&lt;/span&gt; &amp;amp;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Getting Help
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://trac.edgewall.org/wiki/TracFaq" rel="noopener noreferrer"&gt;Trac FAQ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://trac.edgewall.org/wiki/TracGuide" rel="noopener noreferrer"&gt;Trac Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://trac.edgewall.org/wiki/MailingList" rel="noopener noreferrer"&gt;Trac Mailing Lists&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Contact
&lt;/h1&gt;

&lt;p&gt;Please let me know if you discover errors in this guide that need to be corrected.&lt;/p&gt;

</description>
      <category>trac</category>
      <category>linux</category>
      <category>git</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
