#!/usr/bin/php {"0":{"url":"https:\/\/terminaladdict.com\/php\/2011\/02\/24\/disable-the-new-admin-bar-in-wordpress.html","title":"Disable the new admin bar in wordpress","content":" Disable the new admin bar in wordpress\n Posted on 24 Feb 2011 | Categories:\n php\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nYep a geeky thing .. today word press updated to version 3.1\nIt comes with a new \u201cadmin bar\u201d that can upset older themes, however disabling it is not that hard (if you know your way around wordpress coding)\nin your themes folder there is a file called functions.php\nadd this to the end of the file:\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"1":{"url":"https:\/\/terminaladdict.com\/css\/2011\/05\/06\/terminaladdict-version-2-html5-css3.html","title":"TerminalAddict version 2 ( HTML5 & CSS3 )","content":" TerminalAddict version 2 ( HTML5 & CSS3 )\n Posted on 06 May 2011 | Categories:\n css\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nis this HTML5 and CSS3 I see before me?\nYep teh sexy. That\u2019s what HTML5 and CSS3 provide.\nIf you\u2019re viewing this in internet explorer version 8 or earlier you\u2019re probably wondering what wrong with my website; if you\u2019re viewing this in just about any other browser you\u2019;re probably thinking .. wicked dude, good work bustin\u2019 out the HTML5 and CSS3 :)\nShablamo\nThat\u2019s the technical term .. shablamo :)\nVersion two I\u2019ve tried a few different things\nHTML5 and CSS3 (who cares about old browsers?)\n RGBa backgrounds and box-shadows\n Deep integration with facebook (notice the comments are FB comments?)\nNot sure what works and what doesn\u2019t yet .. guess I\u2019ll figure it our over time :)\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"2":{"url":"https:\/\/terminaladdict.com\/css\/2011\/05\/08\/flared-borders-with-css.html","title":"Flared Borders with CSS","content":" Flared Borders with CSS\n Posted on 08 May 2011 | Categories:\n css\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nI want a Pure CSS menu with nice rounded corners\nWell here\u2019s the thing :) .. This article show a very\u00a0elegant\u00a0way of\u00a0achieving\u00a0just that !!!\n Ever wondered how to create an element that flares into another using only\u00a0CSS? Here\u2019s a quick tutorial using existing\u00a0CSS attributes, in combination with\u00a0CSS\u00a0generated content, to produce the effect using no images at all, and no additional markup. And it falls back gracefully for older browsers.\nhttp:\/\/orderedlist.com\/blog\/articles\/flared-borders-with-css\/\nI\u2019l\u00a0definitely\u00a0be using this technique in the future, that\u2019s just damned\u00a0beautiful\u00a0:)\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"3":{"url":"https:\/\/terminaladdict.com\/osx\/2011\/05\/08\/why-safari-why-you-do-this.html","title":"Why Safari? Why you do this?","content":" Why Safari? Why you do this?\n Posted on 08 May 2011 | Categories:\n osx\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nOr why Safari on my iPad thinks it best to undo all my work!\nSo this morning started out with a cooking breakfast, thanks totally to a thoughtful daughter and a deserving wife :) Somehow I just ended up scoring bacon and eggs too !! #winning :)\nSo I\u00a0quietly\u00a0sit down with my cooked breakfast, my iPad, and the news. so far so good.\nNews css tricky menu I see, quiet nice I think to myself, should probably pay that some attention in the future I think to myself \u201c *ping* \u201c that\u2019s the sound of me having a great idea.\nI know I\u2019ll post it on TerminalAddict.com, share it with the world, AND it will keep a record of the URL so I can check it later on in the day .. .brilliant !\nHowever, if you ever tried to compose something in Safari, on an iPad, you know quite well that it is difficult, typing html is not the best on an iPad; copying and pasting is a bit slow .. .y\u2019get the drill.\nTurns out Safari thinks \u201cI haven\u2019t refreshed this window for a while, better do it now\u201d; it doesn\u2019t matter that I have a form with content in it, the page hasn\u2019t changed for 30 seconds; OH .. and it deletes all my content in the form !!!!\nGah\n*shakes fist*\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"4":{"url":"https:\/\/terminaladdict.com\/linux\/2011\/05\/11\/the-shortest-straw-or-url.html","title":"The shortest straw (or URL?)","content":" The shortest straw (or URL?)\n Posted on 11 May 2011 | Categories:\n linux\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nSo todays project was shorten my URLs :)\nSeems simple enough, I\u2019ve been using bit.ly for a while mainly to ease my tweetdeck usage :) But last night I thought \u201cmyself\u201d I thought \u201cyou should do your own URL shortening\u201d.\nI\u2019ve seen \u201cthat guy\u201d ben do it :) http:\/\/www.ben.geek.nz\/ .. can\u2019t be that hard :)\nSo some googling\u00a0around\u00a0to what my options are turns out I need that sweet short domain name.\nSo I got link2.nz, take a look, register and start tracking your links - like a boss!\n There is some stuff I don\u2019t do which maybe I should ? bad word filtering etc? not sure .. I\u2019ll think about that. If it turns into a spam fest then I will make available to registered users only.\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"5":{"url":"https:\/\/terminaladdict.com\/osx\/2011\/05\/12\/why-my-ipad-sits-idle-and-doesnt-get-used.html","title":"Why my iPad sits idle, and doesn't get used","content":" Why my iPad sits idle, and doesn't get used\n Posted on 12 May 2011 | Categories:\n osx\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nWell it seems maybe the honeymoon is over?\nI bought this thing late last year, as I was sick of carting around my heavy laptop. \u00a0I figured the \u201creal\u201d use of my laptop was basically access to email, contacts, and calendars while I\u2019m mooching about Hamilton. I could of course do this all with my phone, but somehow the iPad just seemed better.\nOf course I\u2019m a gadget freak too, so that had something to do with buying this thing :)\nSo now some months on I\u2019ve made a few changes in my life. I shut down my exchange server, and moved all my mail,\u00a0calendar, and contacts to a\u00a0Google\u00a0apps account. I splashed out and bought an Android phone (also because I a gadget freak), and I read an interesting article on m.google.com and how this can easily replace my exchange server for my mobile devices.\nSo now I have Chrome open all day on my desktop at work, with my google apps account open in one window, my Android phone \u201cchecking in\u201d, and basically no \u201creal\u201d reason why I should be carrying my iPad.\nAgreed it is still an awesome gadget, a great ebook reader, and handy \u201ccouch\u201d computer. Can anyone give me any great ideas of what I could do with this bad boy?\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"6":{"url":"https:\/\/terminaladdict.com\/networking\/2011\/05\/16\/god-bless-fibre-ultrafast-broadband.html","title":"God bless fibre (ultrafast broadband)","content":" God bless fibre (ultrafast broadband)\n Posted on 16 May 2011 | Categories:\n networking\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nI\u2019ve long been a fan of fast internet. When I built my country home 8 years ago I paid an extra $5000 to get a huge pole installed, so I could get wireless delivered (17kms line of site). At the time this was pretty cutting edge stuff, and\u00a0expensive\u00a0!!! but everything in my house uses the internet; my TV (TiVo) my phones (voip) my cell phones (3 android phones in the house) plus my idle iPad.\nContent, my\u00a0kingdom\u00a0for content\nI\u2019ve also been pretty good friends with the folks (or at least one of them) at Velocity Networks, so I\u2019ve had my unfair share of information from network providers. Content is king !\nNo body wants a fast connection, just so they can say they have a fast connection (well maybe I do :) ) but really we want content don\u2019t we? TV on-demand, game servers, hosted movies, content .. content .. content! but what content?\nHowever the NZ government seems to be working against us with an ill-informed anti-piracy\u00a0law that removes any burden of proof; we\u2019re all just scared out of our wits to share anything in case we get the book thrown at us.\nSo how is ultrafast broadband supposed to succeed ?\nMore game servers? !!!!\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"7":{"url":"https:\/\/terminaladdict.com\/networking\/2011\/05\/18\/pirates-vs-librarians.html","title":"Pirates vs Librarians","content":" Pirates vs Librarians\n Posted on 18 May 2011 | Categories:\n networking\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nYep it\u2019s the important issues I consider !!!\nActually this is a somewhat important topic in New Zealand really; the laws surrounding anti-piracy and what-not in NZ. Today the NZ Herald published a story about libraries having to possibly remove all internet access.\nIt\u2019s what I have been trying to explain to people all along; there is no burden of proof, and it will affect small business in NZ. \u00a0Possibly my message hasn\u2019t been getting through because I engage \u201crant\u201d mode when I talking; which is probably not conducive to listening to what I have to say :)\nNow I\u2019m no saint I\u2019ll give you that, but, and here\u2019s my thing, if I see value then I don\u2019t mind paying .. no problem in fact, I\u2019ll pay!\nComputer games for instance; I spend money, because I see value in what I\u2019m buying, just take a look at my Steam account, see .. I spend money! \u00a0But if there is no value, I refuse to pay ..\nsky tv for many years took money from me, all the while slowly but surely, increasing the\u00a0amount\u00a0of advertising I had to sit through, the value\u00a0diminished to where I could no longer stand giving them any money. Same deal with Vodafone. I was a\u00a0Vodafone\u00a0customer for near on a trillion years, but have just recently switch to 2degrees; better value\nThe real cure to this needs to be a better thought out way of selling movies, tv shows, and all this pirate nonsense. Better value !! that\u2019s what I want.\nIt\u2019s all related I tell ya \u2026. fibre in our country could be an enabler to a fix for this problem.\u00a0We are meant to be embracing technology, not hindering it. The current climate is heading towards\u00a0stifling\u00a0technology\u00a0advancement!\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"8":{"url":"https:\/\/terminaladdict.com\/networking\/2011\/05\/23\/more-bandwidth-yes-please-mr-pacific-fibre.html","title":"more bandwidth? yes please Mr Pacific Fibre","content":" more bandwidth? yes please Mr Pacific Fibre\n Posted on 23 May 2011 | Categories:\n networking\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nIt seems the international community is starting to notice some things in the NZ internet space. This recent story on El reg & Nz boffins anchor new submarine cable\n New Zealand\u2019s new US$400m submarine communications cable project, Pacific Fibre, has signed Reannz (Research & Education Advanced Network NZ) as its first customer.\n The Pacific Fibre undersea cable system will connect Australia to the United States with two fibre optic cables via New Zealand and should bring more competitive pricing to the international transmission market \u2013 it will go head-to-head with the incumbent Southern Cross Cable network.\nThis pleases me :) Me and the internet we\u2019re like this (*crosses fingers*)\u00a0\nSo to see my precious (nah, I don\u2019t really call it that :) ) possibly developing is great news. There is a *thing* coming together in NZ with fibre to the home, pacific fibre !! I\u2019m excited!\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"9":{"url":"https:\/\/terminaladdict.com\/php\/2011\/06\/02\/google-plus-one.html","title":"Google Plus one (+1) on WordPress Theme","content":" Google Plus one (+1) on WordPress Theme\n Posted on 02 Jun 2011 | Categories:\n php\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nHere\u2019s one for the web developers of the world. Google plus one went live today, so I chucked together a couple of simple functions, to include in your WordPress functions.php theme file.\n"},"10":{"url":"https:\/\/terminaladdict.com\/development\/2013\/04\/16\/install-a-ram-drive-in-windows-7.html","title":"Install a ram drive in Windows 7","content":" Install a ram drive in Windows 7\n Posted on 16 Apr 2013 | Categories:\n development\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nor How to move the Firefox or Chrome cache to a RAM disk and speed up surfing by 20% or more\nIf you\u2019re as old as me, you probably remember what a RAM drive is.\nBack in the golden ages of computing, we had to squeeze every last bit of juice out of our computers (usually for the purpose of playing Quake), you could load a program into a RAM drive; a virtual drive made out of unused RAM. As you probably know, RAM is a lot faster than your hard drive.\nFast forward to today, and it\u2019s all about Solid State Drives. Grab one of those bad boys, and your frame rate drops, apps go faster, all sorts of awesomeness happens. Unfortunately a solid state drive will cost you your first born child. Still, with the amount of time I (and probably you) spend in a browser, wouldn\u2019t it be cool to sort this out so at least the browser will rocket along?\nWith a RAM drive, you can make the chrome, firefox, IE, whatever - always load some stuff from memory. This speeds up the entire browsing experience by a significant margin. The browser starts in a flash, switching between tabs feels faster, and page load times can be reduced by 20% or more!\nThings you will need to achieve this:\nRam disk software\u00a0.. The free version of DataRam\u2019s ramdisk software will do you\n Spare ram - I have 16gb in my desktop, so have plenty spare\n Administration access to your PC .. sorry corporate users, you\u2019ll have to ask you system administrator :)\nInstructions:\nDownload the Ram disk software and install it to your system.\n Once installed you can copy my system here which uses a 4092 MB Ram Disk. You may set a smaller or larger drive to use. This is up to you. (a drive larger than 4092 will require a paid version of Ramdisk)\n Set what you see in the screen shots below.\nNotice the drive is set to Unformatted. You will see why in a soon.\nCreate the image.\nA note here: You may have to play around with which tick boxes. I had to untick \u201cLoad disk image at startup\u201d then tick \u201cCreate temp\u201d and \u201cDisk Label\u201d then re-tick \u201cLoad disk image at startup\u201d.\nOnce you have set what you see in the above pic hit Start RAMDisk.\nNow you need to mount the drive and format it.\nCreate the file system.\ngo to: Start -> Control Panel -> System and Security -> Administrative Tools -> Computer Management -> Disk Management.\nHere you should now be greeted with a prompt that you have a new drive.\nMount the drive and quick format it NTFS, give the name RamDrive and assign letter R (R for ramdrive :) ), I also used compression (it\u2019s all in ram, compression should be fast as ! :) )\nOnce the drive is formatted you\u00a0should\u00a0see your new ramdrive in \u201cMy Computer\u201d .. go have a look.\nPreparing the file system.\nOpen the RamDrive.\n Create 2 folders if you use Internet Explore and Firefox. One called IE_Cache and the other named FF_Cache.\nNow reboot your PC to make sure the RamDisk is working correctly.\nNote: \u00a0RamDisk saves your settings, but if you feel the need (which I did), in the ramdisk windows select the file menu, and click save settings.\nNote: Shutdown should take a little longer than normal, this is due to the image of data on the RamDisk being written to the hard drive. Your computer startup should also take a few seconds longer than normal, this is becasue the Ramdisk is being formatted then the image that was written to the hard drive is mounted on the RamDisk.\u00a0\nMoving firefox cache.\nOpen up Firefox. In the address bar type about:config\nClick the I\u2019ll be careful I promise button.\nRight click anywhere in the values in the lower portion of the screen and choose New -> String.\nType in browser.cache.disk.parent_directory into the \u201cPreference name\u201d\nClick OK.\nIn the next window type in R:\\FF_Cache in the \u201cstring value\u201d (if R: is the RamDisk and you created a folder called FF_Cache).\nClick OK.\nRestart Firefox ! That\u2019s it .. now all your firefox cache is stored on the ram drive, and things should be much faster!\nInternet Explorer cache.\nYou will need to move Temporary Internet Files folder of Internet Explorer to make it store temporary internet files and all cache data to the RamDrive.\nOpen Internet Options.\nOn the General tab look for \u201cTemporary Internet files\u201d or \u201cBrowsing history\u201d and hit Settings.\nThen hit Move folder and point to the Cache folder you made on the RamDisk, e.g. R:\\IE_Cache\nYou can also set the \u201cDisk space\u201d to be used, do what ever feels good :)\nMoving TEMP and TMP Folder\nNote: you have rebooted right? you MUST reboot before moving the TEMP and TMP directories, otherwise you will lose all the work you have done\u00a0previously.\nThis tweak takes the Windows TEMP folder and also the TMP folder, and moves it to the RamDrive.\ngo to:\u00a0Start Menu -> Right-Click Computer -> Properties -> Advanced System Settings -> Advanced Tab\nClick on Environment Variables.\nSelect The TEMP variable and then click Edit.\nThen change the Variable Value to where the RamDrive is. I created a Temp folder on my R: drive, i.e. R:\\Temp.\nRepeat the same thing for the TMP folder and click OK.\nGoogle Chrome cache\nOk this is a bit trickier .. sorry .. you\u2019ll need administrator access, and you\u2019ll need to do stuff in a terminal (also known as a command or cmd window).\nfirstly find out where Chrome is installed, you may have look at the properties of the start menu or desktop shortcut? you could try this:\nWhile chrome is running, right click on your task bar and select start task manager.\n Find any chrome.exe right click on it and select open file location.\nIf you use this method you need to navigate one directory up,\u00a0because\u00a0what I really want is the location of the User Data folder.\nMine was this:\u00a0C:\\Users\\Paul\\AppData\\Local\\Google\\Chrome\\User Data\\Default\nOk, so you\u2019ve found it? close chrome, best open up task manager and make sure there is no chrome.exe application running.\ngo to: Start Menu->All Programs->Accessories->Command Prompt\nRight click and select Run as administrator\nMake sure Chrome is not running then rename the Chrome cache folder like this: ren \u201cC:\\Users\\Paul\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\cache\u201d \u201cC:\\Users\\Paul\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\cache.old\u201d\ntype in this:\u00a0mklink \/d \u201cC:\\Users\\Paul\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\cache\u201d \u201cR:\\ChromeBrowserCache\u201d\nNote: You will need to change the directory to the directory that you use (I\u2019m guessing your name is probably not Paul :) )\nThis creates a \u201csym link\u201d to your ramdrive for your chrome cache.\nGoogle Chrome: 1 step further\nSo I live my life inside Google Chrome, I use it for development, documentation, my email, almost all forms of communication .. lots of things, so I thought, why not run the entire Chrome app in my ram drive.\nFirstly create a directory on your Ramdrive, I created:\u00a0R:\\Applications\\Chrome\nMake sure Chrome is not running then rename the Chrome folder like this: ren \u201cC:\\Users\\Paul\\AppData\\Local\\Google\\Chrome\u201d \u201cC:\\Users\\Paul\\AppData\\Local\\Google\\Chrome.old\u201d\nAgain, make sure Chrome.exe is not running, then do this:\u00a0mklink \/d \u201cC:\\Users\\Paul\\AppData\\Local\\Google\\Chrome\u201d \u201cR:\\Applications\\Chrome\u201d\nNote: You will need to change the directory to the directory that you use (I\u2019m guessing your name is probably not Paul )\nNow you have the complete application running from your ramdrive (already in memory). To\u00a0confirm\u00a0this, open Chrome, then open a task manager, find Chrome.exe, right click and select open file location, it should go directly to your ramdrive folder.\nThe downloads folder\nSo I\u2019m always downloading things; mostly little things, website themes, PDF docs, wordpress source, whatever -things I\u00a0generally\u00a0don\u2019t want to keep, \u00a0but I need for a short time. SO I decided to move my Downloads folder to the ramdrive as well.\nFirstly create a folder on your ramdrive i.e.\u00a0R:\\Downloads\nNext, rename your downloads folder like this: ren \u201cC:\\Users\\Paul\\Downloads\u201d \u201cC:\\Users\\Paul\\Downloads.old\u201d\nNow sym link your downloads folder like this:\u00a0mklink \/d \u201cC:\\Users\\Paul\\Downloads\u201d \u201cR:\\Downloads\u201d\nNote: You will need to change the directory to the directory that you use (I\u2019m guessing your name is probably not Paul )\nConclusion\nThe performance improvements is impressive. Apps (firefox, IE, and Chrome) open so fast ! Plus there is an added benefit of not having to write to your hard drive all the time, adding life to your hard drive. If you are an SSD (Solid State Drive) user this will be important to you! as SSDs have a limited number of writes in their lifetime, why waste those writes on browser cache ?\nI paid for this app so I can create a larger ram drive with the intention of storing my apps on it. A good place to start might be\u00a0http:\/\/portableapps.com,\u00a0where you can download and run things without having to install them.\nMeasuring the real-world improvement of a RAM disk is tricky. I found that page load times were reduced by around 20%. Shutting down and restarting the browser is also a lot quicker.\nIf you have any other tips for speeding up the browser cache, leave a comment!\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"11":{"url":"https:\/\/terminaladdict.com\/php\/css\/2018\/10\/01\/Pauls-Personal-Homepage.html","title":"Pauls Personal Homepage","content":" Pauls Personal Homepage\n Posted on 01 Oct 2018 | Categories:\n php,\n css\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nAfter Google Homepage closed down I wrote my own rss aggregator using php and cron.\nViewable at https:\/\/home.paulwillard.nz\nCode written by Alex Kras\n Code written by David Wals\n xsltproc\n atom2rss.xsl\n wget\n php-xml\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"12":{"url":"https:\/\/terminaladdict.com\/bash\/linux\/2018\/10\/02\/Netonix-backup-script.html","title":"Netonix Backup Script","content":" Netonix Backup Script\n Posted on 02 Oct 2018 | Categories:\n bash,\n linux\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nWorking for a WISP I entensively use Netonix switches. I was asked to code a backup script with parameters in BASH.\nSo I was asked to code a script that accepts an IP address, and a name, that would backup a switch at IP address to name.tar\nThis script will show my coding style.\nIt requires a public key ssh access to the switch for the root user to be setup first.\nYou can also pass the script -q to surpress any output.\n#!\/bin\/bash\n## CONFIGURATION PARAMETERS\n# The ssh user name on remote server\nREMOTE_USER=\"root\"\n# The path to the used ssh key file (if exists)\nKEYFILE=\"\/path\/to\/ssh-key\"\n## NO NEED TO EDIT BELOW THIS LINE\n# Quiet mode\nQUIET=false\n# red colour for big fat error\nRED='\\033[0;31m'\nNC='\\033[0m' # No Color\n# surpress built-in GETOPTS errors\nOPTERR=0\nVERSION=\"2018-04-10\"\nCheckIP() {\n if [[ \"$1\" =~ ^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$ ]]; then\n ping -c1 \"$1\" > \/dev\/null 2>&1\n if [ \"$?\" = 0 ]; then\n return 0\n else\n echo -e \"\\n${RED}$IP is not reachable${NC}\\n\" 77 help\n fi\n else\n echo -e \"\\n${RED}$IP is not valid${NC}\\n\" 77 help\n fi \n return 0\n}\nCheckDir() {\n DIR=$(dirname \"$1\")\n if [ ! -d \"$DIR\" ]; then\n echo -e \"\\n${RED}Directory $DIR does not exist${NC}\\n\" && help\n fi\n if [ ! -w \"$DIR\" ]; then\n echo -e \"\\n${RED}Directory $DIR is not writable${NC}\\n\" && help\n fi\n return 0\n}\nhelp() {\n SCRIPT_NAME=\"$(basename \"$(test -L \"$0\" && readlink \"$0\" || echo \"$0\")\")\"\n echo \"$SCRIPT_NAME version $VERSION\n$SCRIPT_NAME is a small shell script that backups up a netonix switch\nPut your settings in the config section in the script itself!\nOptions\n -q quiet mode\n -i IP address of the switch\n -n name of file out put (example: -n thisName would produce thisName.tar)\n this could also include a path i.e. \/tmp\/thisName.tar\n -h show this screen\n\"\nexit 0\n}\n# Yippieeh, commandline parameters\nwhile getopts i:n:hq option \ndo\n case \"${option}\" in\n i) REMOTE_HOST=${OPTARG};;\n n) NAME=${OPTARG};;\n q) QUIET=true;;\n h) help;;\n *) help;;\n esac\ndone\nshift $((OPTIND-1))\ntest -z \"${REMOTE_HOST}\" && echo -e \"\\n${RED}IP address is mandatory${NC}\\n\" && help\ntest -z \"${NAME}\" && echo -e \"\\n${RED}NAME is mandatory${NC}\\n\" && help\nCheckIP $REMOTE_HOST\nCheckDir $NAME\nif [ \"$QUIET\" = \"false\" ]; then echo \"I'm continuing\"; fi\n# Connect to remote switch and perform a local backup\nif [ \"$QUIET\" = \"false\" ]; then echo \"I'm connecting to $REMOTE_HOST to performa a local backup\"; fi\nRESULTS=$(ssh -i $KEYFILE $REMOTE_USER@$REMOTE_HOST '\/usr\/bin\/config_backup')\nif [ \"$QUIET\" = \"false\" ]; then \n if [ \"$?\" = 0 ]; then echo \"Success\"; else echo \"\\n${RED}Uh-oh !! Failed running backup on the $REMOTE_HOST ${NC}\\n\"; fi\nfi\n# Grab a copy of the backup from the remote switch and save it\nif [ \"$QUIET\" = \"false\" ]; then echo \"I'm downloading backup from $REMOTE_HOST and saving to $NAME\"; fi\nRESULTS=$(scp -i $KEYFILE $REMOTE_USER@$REMOTE_HOST:\/tmp\/wispswitch_config.tar $NAME.tar)\nif [ \"$QUIET\" = \"false\" ]; then \n if [ \"$?\" = 0 ]; then echo \"Success\"; else echo -e \"\\n${RED}Uh-oh !! Failed downloading from $REMOTE_HOST ${NC}\\n\"; fi\nfi\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"13":{"url":"https:\/\/terminaladdict.com\/linux\/bash\/2018\/10\/03\/NFTables-bash-script.html","title":"Nftables Bash Script","content":" Nftables Bash Script\n Posted on 03 Oct 2018 | Categories:\n linux,\n bash\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nIn 2018 I changed from running iptables to running nftables. This is my BASH script I use on my firewall.\nThis script firstly removes any remaining iptables rules, and kernel modules (as they can cause problems).\nit then loads the new nftables rules.\nI\u2019ve included examples of accepting ports, as well as forwarding ports to a server.\nI also have another file called \u201cbanned_ips\u201d which is just a list of IPs or networks that I want to completely ban.\n#!\/bin\/bash\nSYSCTL=\"\/sbin\/sysctl -w\"\nnft=\"\/usr\/sbin\/nft\"\nIPT=\"\/sbin\/iptables\"\nBANNED=\"\/etc\/banned_ips\"\n# DEAL WITH IPTABLES .. you can probably safely remove this section once things settle\necho \"Flushing IPTables ...\"\n# Reset Default Policies\n$IPT -P INPUT ACCEPT\n$IPT -P FORWARD ACCEPT\n$IPT -P OUTPUT ACCEPT\n$IPT -t nat -P PREROUTING ACCEPT\n$IPT -t nat -P POSTROUTING ACCEPT\n$IPT -t nat -P OUTPUT ACCEPT\n$IPT -t mangle -P PREROUTING ACCEPT\n$IPT -t mangle -P OUTPUT ACCEPT\n# Flush all rules\n$IPT -F\n$IPT -t nat -F\n$IPT -t mangle -F\n# Erase all non-default chains\n$IPT -X\n$IPT -t nat -X\n$IPT -t mangle -X\necho \"Removing IPTables kernel modules ...\"\nrmmod iptable_mangle\nrmmod iptable_nat\nrmmod ipt_MASQUERADE\n# FINISHED DEALING WITH IPTABLES ..\n# Internet Interface\nINET_IFACE=\"enp0s20f0\"\n# LAN Interface Information\nLOCAL_IFACE=\"enp3s0\"\nLOCAL_IP=\"192.168.1.254\"\nLOCAL_NET=\"192.168.1.0\/24\"\nLOCAL_BCAST=\"192.168.1.255\"\n# Localhost Interface\nLO_IFACE=\"lo\"\nLO_IP=\"127.0.0.1\"\n# define some commonly used hosts\nSERVER=\"192.168.1.2\"\n# nft does not do save and restore (in the current debian it screws things up)\n# Save and Restore arguments handled here\n# if [ \"$1\" = \"save\" ]\n# then\n# echo -n \"Saving firewall to \/etc\/nftables.save ... \"\n# $nft list ruleset > \/etc\/nftables.save\n# echo \"done\"\n# exit 0\n# elif [ \"$1\" = \"restore\" ]\n# then\n# echo -n \"Restoring firewall from \/etc\/nftables.save ... \"\n# $nft -f \/etc\/nftables.save\n# echo \"done\"\n# exit 0\n# fi\n###############################################################################\n#\n# Load Modules\n#\necho \"Loading kernel modules ...\"\n# \/sbin\/modprobe ip_tables\n\/sbin\/modprobe nf_nat\n\/sbin\/modprobe nf_nat_ipv4\n\/sbin\/modprobe nf_conntrack\n\/sbin\/modprobe nf_conntrack_ipv4\n\/sbin\/modprobe nf_conntrack_irc\n\/sbin\/modprobe nf_nat_ftp\n\/sbin\/modprobe nf_conntrack_ftp\n###############################################################################\n#\n# Kernel Parameter Configuration\n#\n# See http:\/\/ipsysctl-tutorial.frozentux.net\/chunkyhtml\/index.html\n# for a detailed tutorial on sysctl and the various settings\n# available.\n# Required to enable IPv4 forwarding.\n# Redhat users can try setting FORWARD_IPV4 in \/etc\/sysconfig\/network to true\n# Alternatively, it can be set in \/etc\/sysctl.conf\nif [ \"$SYSCTL\" = \"\" ]\nthen\n echo \"1\" > \/proc\/sys\/net\/ipv4\/ip_forward\nelse\n $SYSCTL net.ipv4.ip_forward=\"1\"\nfi\n# This enables dynamic address hacking.\n# This may help if you have a dynamic IP address \\(e.g. slip, ppp, dhcp\\).\n#if [ \"$SYSCTL\" = \"\" ]\n#then\n# echo \"1\" > \/proc\/sys\/net\/ipv4\/ip_dynaddr\n#else\n# $SYSCTL net.ipv4.ip_dynaddr=\"1\"\n#fi\n# This enables SYN flood protection.\n# The SYN cookies activation allows your system to accept an unlimited\n# number of TCP connections while still trying to give reasonable\n# service during a denial of service attack.\nif [ \"$SYSCTL\" = \"\" ]\nthen\n echo \"1\" > \/proc\/sys\/net\/ipv4\/tcp_syncookies\nelse\n $SYSCTL net.ipv4.tcp_syncookies=\"1\"\nfi\n# This enables source validation by reversed path according to RFC1812.\n# In other words, did the response packet originate from the same interface\n# through which the source packet was sent? It's recommended for single-homed\n# systems and routers on stub networks. Since those are the configurations\n# this firewall is designed to support, I turn it on by default.\n# Turn it off if you use multiple NICs connected to the same network.\nif [ \"$SYSCTL\" = \"\" ]\nthen\n echo \"1\" > \/proc\/sys\/net\/ipv4\/conf\/all\/rp_filter\nelse\n $SYSCTL net.ipv4.conf.all.rp_filter=\"1\"\nfi\n# This kernel parameter instructs the kernel to ignore all ICMP\n# echo requests sent to the broadcast address. This prevents\n# a number of smurfs and similar DoS nasty attacks.\nif [ \"$SYSCTL\" = \"\" ]\nthen\n echo \"1\" > \/proc\/sys\/net\/ipv4\/icmp_echo_ignore_broadcasts\nelse\n $SYSCTL net.ipv4.icmp_echo_ignore_broadcasts=\"1\"\nfi\n# This option can be used to accept or refuse source routed\n# packets. It is usually on by default, but is generally\n# considered a security risk. This option turns it off.\nif [ \"$SYSCTL\" = \"\" ]\nthen\n echo \"0\" > \/proc\/sys\/net\/ipv4\/conf\/all\/accept_source_route\nelse\n $SYSCTL net.ipv4.conf.all.accept_source_route=\"0\"\nfi\n# This option accepts only from gateways in the default gateways list.\nif [ \"$SYSCTL\" = \"\" ]\nthen\n echo \"1\" > \/proc\/sys\/net\/ipv4\/conf\/all\/secure_redirects\nelse\n $SYSCTL net.ipv4.conf.all.secure_redirects=\"1\"\nfi\n# This option logs packets from impossible addresses.\nif [ \"$SYSCTL\" = \"\" ]\nthen\n echo \"1\" > \/proc\/sys\/net\/ipv4\/conf\/all\/log_martians\nelse\n $SYSCTL net.ipv4.conf.all.log_martians=\"1\"\nfi\n# This option allows connection tracking for helpers (like ftp and irc connection tracking)\nif [ \"$SYSCTL\" = \"\" ]\nthen\n echo \"1\" > \/proc\/sys\/net\/netfilter\/nf_conntrack_helper\nelse\n $SYSCTL net.netfilter.nf_conntrack_helper=\"1\"\nfi\n###############################################################################\n#\n# Flush Any Existing Rules or Chains\n#\n$nft flush ruleset\nif [ \"$1\" = \"stop\" ]\nthen\n echo \"Firewall completely flushed! Now running with no firewall.\"\n exit 0\nfi\n$nft add table filter\n$nft add chain filter input { type filter hook input priority 0\\; policy drop \\; }\n$nft add chain filter forward { type filter hook forward priority 0\\; policy drop \\; }\n$nft add chain filter output { type filter hook output priority 0\\; policy accept \\; }\n$nft add table nat\n$nft add chain nat prerouting { type nat hook prerouting priority 0 \\; }\n# this is a router so masq\n$nft add chain nat postrouting { type nat hook postrouting priority 100 \\; meta oifname $INET_IFACE masquerade\\; }\n# Banned IPs\nif [ -f \"$BANNED\" ]; then\n last=`tail -1 $BANNED`\n BANNED_LIST=\"\"\n while read BANNED_IP; do\n if [ $BANNED_IP == $last ]; then\n BANNED_LIST=\"$BANNED_LIST$BANNED_IP\"\n else\n BANNED_LIST=\"$BANNED_LIST$BANNED_IP, \"\n\tfi\n done "},"14":{"url":"https:\/\/terminaladdict.com\/linux\/bash\/2018\/10\/04\/Monitoring-an-APC-UPS.html","title":"Monitoring An Apc Ups","content":" Monitoring An Apc Ups\n Posted on 04 Oct 2018 | Categories:\n linux,\n bash\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nI have an APC UPS which I like to monitor, and graph, this is the code I use to do so.\nSo I created a bash script to monitor and graph the state of my UPS.\nFirstly run this script with the \u201ccreate\u201d parameter ups.sh create then create a cron job to regularly update:\n* * * * * root \/usr\/local\/bin\/ups.sh update > \/dev\/null && \/usr\/local\/bin\/ups.sh graph > \/dev\/null\nThis script requires rrdtool to be installed.\n#!\/bin\/bash\nTRAF=\/var\/www\/html\nUPS=192.168.1.98\n case $1 in (create)\n \/usr\/bin\/rrdtool create $TRAF\/ups.rrd -s 60 \\\n DS:upsBat:GAUGE:600:0:U \\\n DS:upsLoad:GAUGE:600:0:U \\\n DS:upsBatRun:GAUGE:600:0:U \\\n RRA:AVERAGE:0.5:1:4320 \\\n RRA:AVERAGE:0.5:1440:3 \\\n RRA:MIN:0.5:1440:3 \\\n RRA:MAX:0.5:1440:3;;\n (update)\n upsBat=`snmpget -v1 -c public $UPS 1.3.6.1.4.1.318.1.1.1.2.2.1.0 | awk '{ print $4 }'`\n upsLoad=`snmpget -v1 -c public $UPS 1.3.6.1.4.1.318.1.1.1.2.2.8.0 | awk '{ print $4 }'`\n upsBatRun=`expr \\`snmpget -v1 -c public $UPS .1.3.6.1.4.1.318.1.1.1.2.2.3.0 | awk '{ print $4 }' | sed 's\/\\((\\|)\\)\/\/g'\\` \/ 6000`\n \/usr\/bin\/rrdtool update $TRAF\/ups.rrd N:$upsBat:$upsLoad:$upsBatRun;;\n (graph)\n \/usr\/bin\/rrdtool graph $TRAF\/ups.png \\\n --start \"-3day\" \\\n -c \"BACK#000000\" \\\n -c \"SHADEA#000000\" \\\n -c \"SHADEB#000000\" \\\n -c \"FONT#DDDDDD\" \\\n -c \"CANVAS#202020\" \\\n -c \"GRID#666666\" \\\n -c \"MGRID#AAAAAA\" \\\n -c \"FRAME#202020\" \\\n -c \"ARROW#FFFFFF\" \\\n -u 1.1 -l 0 -v \"UPS\" -w 1100 -h 250 -t \"UPS - `\/bin\/date +%A\", \"%d\" \"%B\" \"%Y`\" \\\n DEF:upsBatA=$TRAF\/ups.rrd:upsBat:AVERAGE \\\n DEF:upsLoad=$TRAF\/ups.rrd:upsLoad:AVERAGE \\\n DEF:upsBatRun=$TRAF\/ups.rrd:upsBatRun:AVERAGE \\\n \"CDEF:upsBat=upsBatA,1,*\" \\\n AREA:upsBatRun\\#00FF00:\"Battery Runtime (Mins)\" \\\n GPRINT:upsBatRun:MIN:\"Min\\: %3.2lf \" \\\n GPRINT:upsBatRun:MAX:\"Max\\: %3.2lf\" \\\n GPRINT:upsBatRun:LAST:\"Current\\: %3.2lf\\j\" \\\n COMMENT:\"\\\\n\" \\\n AREA:upsBat\\#FFFF00:\"Battery Percent\" \\\n GPRINT:upsBat:MIN:\"Min\\: %3.2lf \" \\\n GPRINT:upsBat:MAX:\"Max\\: %3.2lf\" \\\n GPRINT:upsBat:LAST:\"Current\\: %3.2lf\\j\" \\\n COMMENT:\"\\\\n\" \\\n AREA:upsLoad\\#FF0000:\"UPS Load (volts)\" \\\n GPRINT:upsLoad:MIN:\"Min\\: %3.2lf \" \\\n GPRINT:upsLoad:MAX:\"Max\\: %3.2lf\" \\\n GPRINT:upsLoad:LAST:\"Current\\: %3.2lf\\j\";;\n (*)\n echo \"Invalid option.\";;\n esacThe resulting graph looks like this:\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"15":{"url":"https:\/\/terminaladdict.com\/linux\/bash\/osx\/2018\/10\/05\/Debian-Stretch-Timemachine.html","title":"Debian Stretch Timemachine","content":" Debian Stretch Timemachine\n Posted on 05 Oct 2018 | Categories:\n linux,\n bash,\n osx\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nIn 2018 I got a flashy new MacBook Pro. Using the macOS integrated backup solution Time Machine I wanted to build an open source Apple Time Capsule.\nApple Mac OSX doesn\u2019t allow you to use a network share as a backup location.\nThe steps described below are tested on Debian Stretch but might also work on other Debian based distributions like Ubuntu.\nStep 1\nNetatalk, the open source deployment of Apple Filling Protocol (AFP) has to be installed.\nsudo apt-get install netatalk libc6-dev avahi-daemon libnss-mdns\nStep 2\nEdit the hosts line in \/etc\/nsswitch.conf with the editor of your choice. I am using vi.\nsudo vi \/etc\/nsswitch.conf\nThe line should be adjusted as followed:\nhosts: files mdns4_minimal [NOTFOUND=return] dns mdns4 mdns\nStep 3\nCreate the file \/etc\/avahi\/services\/afpd.service\nsudo vi \/etc\/avahi\/services\/afpd.service\nand fill it with this content:\n %h\n _afpovertcp._tcp\n 548\n _device-info._tcp\n 0\n model=TimeCapsule\nStep 4\nNow add the shares for the backups. Edit \/etc\/netatalk\/AppleVolumes.default and add the parameter tm.\nsudo vi \/etc\/netatalk\/AppleVolumes.default\nI have created a timemachine share for my wife and I.\n# The line below sets some DEFAULT, starting with Netatalk 2.1.\n:DEFAULT: options:upriv,usedots,tm\n# By default all users have access to their home directories.\n\/mnt\/timemachine\/paul \"TimeMachine Paul\"\n\/mnt\/timemachine\/helen \"TimeMachine Helen\"\n# End of File\nStep 5\nFinally, Netatalk has to be adjusted.\nsudo vi \/etc\/default\/netatalk\nEdit the folowing variables:\nATALKD_RUN=no\nPAPD_RUN=no\nCNID_METAD_RUN=yes\nAFPD_RUN=yes\nTIMELORD_RUN=no\nA2BOOT_RUN=no\nNow just restart the services for Netatalk and Avahi.\nsystemctl restart netatalk.service\nsystemctl restart avahi-daemon.service\nFinal notes\nEach user must be a real user on your linux server (i.e. useradd paul ).\nYou may have to create and change ownership of the directories (i.e. mkdir -p \/mnt\/timemachine\/paul && chown paul:paul \/mnt\/timemachine\/paul ).\nNow you should be able to access the shares from timemachine.\n Comments\n\t\tPaul\n May 20, 2020 at 02:43 AM\n I\u2019ve just rebuilt this using Ubuntu Focal (2020 release) and this file \/etc\/netatalk\/AppleVolumes.default is no longer used \nInstead I have this file \/etc\/netatalk\/afp.conf \nLooks like this:\n;\n; Netatalk 3.x configuration file\n;\n[Global]\n; Global server settings\n[Timemachine]\npath = \/mnt\/data-volume\/Timemachine\/paul\ntime machine = yes\nalso note, on my Macbook (client) I have to run this command\ndefaults write com.apple.systempreferences TMShowUnsupportedNetworkVolumes 1\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"16":{"url":"https:\/\/terminaladdict.com\/linux\/bash\/2018\/10\/06\/git-server-with-nginx.html","title":"Git Server (with Nginx)","content":" Git Server (with Nginx)\n Posted on 06 Oct 2018 | Categories:\n linux,\n bash\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nFirstly, getting a git server up and running is pretty easy.\nMake sure git is installed aptitude install git\nCreate a git user adduser git\nChange the git user\u2019s shell echo $(which git-shell) >> \/etc\/shells, and then chsh git -s $(which git-shell)\nYou should now be able to initiate a git repo on your server.\ncd ~git && git init --bare my-new-project.git && chown -R git:git my-new-project.git\nThat\u2019s it! You\u2019ve created a git repo, now on your local machine go and clone it.\ngit clone git@myserver:my-new-project.git\nSSH Security\nSecurity is up to you! I have disable password auth in ssh, and loaded my key into ~git\/.ssh\/authorized_keys\nThis is strongly recommended !!! but if you\u2019re building a git server you probably know enough to secure your ssh server. (I hope !)\nConfiguring Nginx\nI\u2019m not going to delve into virtual hosting with Nginx , that\u2019s not in this scope.\nWhat is in scope, is getting nginx to respond accordling to git requests.\nI\u2019ve chosen to serve my git repos over https using a pre-defined sub directory (that doesn\u2019t actually exists) called git\/\nGrab a copy of the following config, chuck it in the appropriate place in nginx then restart nginx.\nlocation ~ (\/git\/.*) {\n\t\tclient_max_body_size 0; # Git pushes can be massive, just to make sure nginx doesn't suddenly cut the connection add this.\n\t\tauth_basic \"Git Login\"; # Whatever text will do.\n\t\tauth_basic_user_file \"\/home\/git\/.htpasswd\";\n\t\tinclude \/etc\/nginx\/fastcgi_params; # Include the default fastcgi configs\n\t\tfastcgi_param SCRIPT_FILENAME \/usr\/lib\/git-core\/git-http-backend; # Tells fastcgi to pass the request to the git http backend executable\n\t\tfastcgi_param GIT_HTTP_EXPORT_ALL \"\";\n\t\tfastcgi_param GIT_PROJECT_ROOT \/home; # \/home\/git is the location of all of your git repositories.\n\t\tfastcgi_param REMOTE_USER $remote_user;\n\t\tfastcgi_param PATH_INFO $1; # Takes the capture group from our location directive and gives git that.\n\t\tfastcgi_pass unix:\/var\/run\/fcgiwrap.socket; # Pass the request to fastcgi\n\t}Securing http\/s with auth\nFinally, let\u2019s put a password on the git repo access via http\/s.\nhtpasswd -c \/home\/git\/.htpasswd myusername\nYou\u2019re done!\nOnce you\u2019ve done that you should be able to check out your repo using http\/s from your local machine.\ngit clone https:\/\/myusername@yourdomain.com\/git\/my-new-project.git\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"17":{"url":"https:\/\/terminaladdict.com\/linux\/bash\/mikrotik\/2018\/10\/07\/Mikrotik-backup-script.html","title":"Mikrotik Backup Script","content":" Mikrotik Backup Script\n Posted on 07 Oct 2018 | Categories:\n linux,\n bash,\n mikrotik\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nI use Mikrotik routers a lot! I work for a WISP and there are a lot of Mikrotik devices.\nThis script requires a public key ssh access to the router for a user to be setup first.\nYou can also pass the script -q to surpress any output.\n#!\/bin\/bash\n## CONFIGURATION PARAMETERS\n# The ssh user name on remote server\nREMOTE_USER=\"user\"\n# The path to the used ssh key file (if exists)\nKEYFILE=\"~\/path\/to\/private_key\"\n## A good way of using this to check into a repo\n# pushd \/my\/git\/repo\n# ~\/git-repos\/mikrotik-backup\/mikrotik-backup.sh -n paulwillard-mikrotik -i 192.168.1.254 -t text\n# tail -n +2 paulwillard-mikrotik.daily.rsc > paulwillard-mikrotik.daily.rsc.tmp && mv paulwillard-mikrotik.daily.rsc.tmp paulwillard-mikrotik.daily.rsc\n# git comit -a\n# git push\n# popd\n## NO NEED TO EDIT BELOW THIS LINE\n# Quiet mode\nQUIET=false\n# red colour for big fat error\nRED='\\033[0;31m'\nNC='\\033[0m' # No Color\n# surpress built-in GETOPTS errors\nOPTERR=0\nVERSION=\"2018-09-21\"\nCheckIP() {\n if [[ \"$1\" =~ ^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$ ]]; then\n ping -c1 \"$1\" > \/dev\/null 2>&1\n if [ \"$?\" = 0 ]; then\n return 0\n else\n echo -e \"\\n${RED}$1 is not reachable${NC}\\n\" && help\n fi\n else\n echo -e \"\\n${RED}$1 is not valid${NC}\\n\" && help\n fi\n return 0\n}\nCheckDir() {\n DIR=$(dirname \"$1\")\n if [ ! -d \"$DIR\" ]; then\n echo -e \"\\n${RED}Directory $DIR does not exist${NC}\\n\" && help\n fi\n if [ ! -w \"$DIR\" ]; then\n echo -e \"\\n${RED}Directory $DIR is not writable${NC}\\n\" && help\n fi\n return 0\n}\nhelp() {\n SCRIPT_NAME=\"$(basename \"$(test -L \"$0\" && readlink \"$0\" || echo \"$0\")\")\"\n echo \"$SCRIPT_NAME version $VERSION\n$SCRIPT_NAME is a small shell script that backups up a Mikrotik router\nPut your settings in the config section in the script itself!\nOptions\n -q quiet mode\n -i IP address of the router\n -n name of file out put (example: -n thisName would produce thisName.daily.rsc or thisName.daily.backup - depending on -t option)\n this could also include a path i.e. \/tmp\/thisName\n -t type of backup either text or full\n -h show this screen\n\"\nexit 0\n}\n# Yippieeh, commandline parameters\nwhile getopts i:n:t:hq option\ndo\n case \"${option}\" in\n i) REMOTE_HOST=${OPTARG};;\n n) NAME=${OPTARG};;\n q) QUIET=true;;\n t) TYPE=${OPTARG};;\n h) help;;\n *) help;;\n esac\ndone\nshift $((OPTIND-1))\ntest -z \"${REMOTE_HOST}\" && echo -e \"\\n${RED}IP address is mandatory${NC}\\n\" && help\ntest -z \"${NAME}\" && echo -e \"\\n${RED}NAME is mandatory${NC}\\n\" && help\ntest -z \"${TYPE}\" && echo -e \"\\n${RED}TYPE is mandatory${NC}\\n\" && help\ncase $TYPE in\n text) BACKUP='\/export compact file=daily'\n BACKUPFILE='daily.rsc'\n ;;\n full) BACKUP='\/system backup save name=daily dont-encrypt=yes'\n BACKUPFILE='daily.backup'\n ;;\n *) echo -e \"\\n${RED}Invalid TYPE${NC}\\n\"\n help\n ;;\nesac\n# concat NAME\nNAME=$NAME.$BACKUPFILE\nCheckIP $REMOTE_HOST\nCheckDir $NAME\nif [ \"$QUIET\" = \"false\" ]; then echo \"I'm continuing\"; fi\n# Connect to remote switch and perform a local backup\nif [ \"$QUIET\" = \"false\" ]; then echo \"I'm connecting to $REMOTE_HOST to performa a local backup\"; fi\nRESULTS=$(ssh -i $KEYFILE $REMOTE_USER@$REMOTE_HOST $BACKUP)\nif [ \"$QUIET\" = \"false\" ]; then\n if [ \"$?\" = 0 ]; then echo \"Success\"; else echo \"\\n${RED}Uh-oh !! Failed running backup on the $REMOTE_HOST ${NC}\\n\"; fi\nfi\n# Grab a copy of the backup from the remote switch and save it\nif [ \"$QUIET\" = \"false\" ]; then echo \"I'm downloading backup from $REMOTE_HOST and saving to $NAME\"; fi\nRESULTS=$(scp -i $KEYFILE $REMOTE_USER@$REMOTE_HOST:$BACKUPFILE $NAME)\nif [ \"$QUIET\" = \"false\" ]; then\n if [ \"$?\" = 0 ]; then echo \"Success\"; else echo -e \"\\n${RED}Uh-oh !! Failed downloading from $REMOTE_HOST ${NC}\\n\"; fi\nfiI actually use this script in a cron job to backup a mikrotik daily.\nI trim the first line from the text backup (which is a date stamp), so git can see the \u201ctrue\u201d changes.\n#!\/bin\/bash\npushd \/path\/to\/git-repo\/mikrotik-backup\ngit pull --quiet\nmikrotik-backup.sh -q -n paulwillard-mikrotik -i 192.168.1.254 -t text\ntail -n +2 paulwillard-mikrotik.daily.rsc > paulwillard-mikrotik.daily.rsc.tmp && mv paulwillard-mikrotik.daily.rsc.tmp paulwillard-mikrotik.daily.rsc\ngit commit -m \"updated backup\" -a\ngit push --quiet\npopd\nexit 0\n Comments\n\t\tAlexander\n July 10, 2019 at 05:34 PM\n Thank you sooo much! Very helpfull\n\t\tj0S3\n March 23, 2021 at 12:45 AM\n Thank you very much\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"18":{"url":"https:\/\/terminaladdict.com\/linux\/bash\/mikrotik\/2018\/10\/08\/tftpd.html","title":"Debian Netboot ( Tftpd )","content":" Debian Netboot ( Tftpd )\n Posted on 08 Oct 2018 | Categories:\n linux,\n bash,\n mikrotik\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nI pretty frequently install debian. There is always some sort of development going on that needs me to fire up a new install.\nI wrote a script to update my Debian Netboot directory etc.\nI download a new Netboot image from Debian, compare the checksums (to make sure the download is good), then override some boot parameters.\nYou need to install a tfpd server.aptitude install tftpd-hpa\n#!\/bin\/bash\nrm -rf \/tmp\/netboot-tmp\/\nmkdir \/tmp\/netboot-tmp\/\ncd \/tmp\/netboot-tmp\/\n# Get image and validation files\nwget http:\/\/deb.debian.org\/debian\/dists\/stable\/main\/installer-amd64\/current\/images\/netboot\/netboot.tar.gz -O \/tmp\/netboot-tmp\/netboot.tar.gz\nwget http:\/\/deb.debian.org\/debian\/dists\/stable\/main\/installer-amd64\/current\/images\/SHA256SUMS -O \/tmp\/netboot-tmp\/SHA256SUMS\n# Check the checksum of the file\nSUM1=`cat SHA256SUMS | grep -F netboot\/netboot.tar.gz | awk '{print $1}'`\nSUM2=`sha256sum netboot.tar.gz | awk '{print $1}'`\nif [ \"$SUM1\" != \"$SUM2\" ]; then\n echo \"Checksum failed for netboot.tar.gz, $SUM2 is not $SUM1\"\n exit -1\nfi\n# Check the checksum of the checksum file\nSUM1=`cat \/tmp\/netboot-tmp\/Release | grep -A 100000 '^SHA256' | grep -F installer-amd64\/current\/images\/SHA256SUMS | awk '{print $1}'`\nSUM2=`sha256sum \/tmp\/netboot-tmp\/SHA256SUMS | awk '{print $1}'`\nif [ \"$SUM1\" != \"$SUM2\" ]; then\n echo \"Checksum failed for SHA256SUMS, $SUM2 is not $SUM1\"\n exit -1\nfi\n# Extract the archive contents\n# cd \/srv\/tftp\nrm -rf \/srv\/tftp\/*\ntar -xf \/tmp\/netboot-tmp\/netboot.tar.gz -C \/srv\/tftp\n# Set the timeout so installation is hands off\nsed 's\/timeout 0\/timeout 1\/' --in-place \/srv\/tftp\/debian-installer\/amd64\/pxelinux.cfg\/default\n# Set up the installer to use the serial console\nsed 's@append vga=788 initrd=debian-installer\/amd64\/initrd.gz --- quiet@append initrd=debian-installer\/amd64\/initrd.gz --- quiet console=ttyS1,115200n1@' --in-place \/srv\/tftp\/debian-installer\/amd64\/boot-screens\/txt.cfg\n# clean up\nrm -rf \/tmp\/netboot-tmp\/To make this super easy to use you can configure your DHCPd server to tell hosts to netboot.\nHere is an example using the isc-dhcpd-server. It assumes your subnet is 192.168.1.0\/24 and the tfpd server is running on 192.168.1.2:\nsubnet 192.168.1.0 netmask 255.255.255.0 {\n .......\n next-server 192.16.1.2;\n filename \"pxelinux.0\";\n}\ngroup {\n next-server 192.168.1.2;\n host tftpclient {\n filename \"pxelinux.0\";\n }\n}Here is an example using Mikrotik. It assumes your subnet is 192.168.1.0\/24 and the tfpd server is running on 192.168.1.2:\n\/ip dhcp-server network\nadd address=192.168.1.0\/24 boot-file-name=pxelinux.0 dns-server=192.168.1.1 domain=example.com gateway=192.168.1.1 next-server=192.168.1.2\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"19":{"url":"https:\/\/terminaladdict.com\/linux\/jekyll\/bash\/development\/2018\/10\/17\/Jekyll-Getting-Started.html","title":"Jekyll Getting Started","content":" Jekyll Getting Started\n Posted on 17 Oct 2018 | Categories:\n linux,\n jekyll,\n bash,\n development\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nSo my web development has taken an interesting path, not that different to some others.\nI start back in 1907 doing hand coded html, then moved to hand coded php, then dreamweaver, then CMS.\nEventually making it to Wordpress then back to PHP, and now to Jekyll\nMy path to adopting Jekyll has been a long one. Every now and then I get a bee in my bonnet about how bloated Wordpress is for many of my web tasks.\nIt\u2019s great for what it was designed for! Helen uses Wordpress in all her websites, and it is a perfect tool for her.\nShe\u2019s not technical, and just wants to publish articles that she types in an online editor; perfect for Wordpress!\nI am technical! and I don\u2019t need all the things that come with Wordpress, in fact what I really want is the fastest loading website possible.\nIn comes Jekyll (plus bootstrap, jquery, and popper.js ).\nSo I faffed about on my Macbook and started converting paulwillard.nz to a Jekyll site.\nafter a few days I realised I\u2019d lost track of what I had installed, and where I had got to with dev.\nSo I thought I\u2019d start from scratch again, and this time document the steps to get a really simple boostrap site up and running.\nBefore I continue I\u2019ve got to give credit to a site that has really helped my journey.\nMade Mistakes - Going Static\n Made Mistakes - Going Static Episode II\n Made Mistakes - Using Jekyll\nI have no idea who this Michael Rose character is, but I reckon he\u2019s taken the same web development path as me, going by his posts!\nSo here we go:\nI start with a dead clean fresh install of Debian Stretch\nInstalling NodeJS and ruby\nLet\u2019s install the deb source key:curl -s https:\/\/deb.nodesource.com\/gpgkey\/nodesource.gpg.key | sudo apt-key add -\nand add to our packages sources.list:\ncat > \/etc\/apt\/sources.list\ndeb https:\/\/deb.nodesource.com\/node_10.x stretch main\ndeb-src https:\/\/deb.nodesource.com\/node_10.x stretch main\nEOFNow let\u2019s install some packages:\naptitude update\naptitude install ruby-full build-essential nodejs treeEnvironment setup\nLet\u2019s install all our gems to our home directory:\ncat > ~\/.bashrc\n### Install Ruby Gems to ~\/gems\nexport GEM_HOME=$HOME\/gems\nexport PATH=$HOME\/gems\/bin:$PATH\nEOF \nsource ~\/.bashrcInstall Jekyll\nLet\u2019s install Jekyll:gem install jekyll bundler\nCreate a Jekyll site\nLet\u2019s start with a blank site:jekyll new mysite --blank\nand add some JS packages from node:\ncd mysite\nnpm init --force\nnpm install bootstrap\nnpm install jquery\nnpm install popper.js_config.yml Setup\nLet\u2019s do a basic _config.yml\nThis will tell Jekyll to search a few different paths for sass\nand tell Jekyll to include node_modules by setting exclude to 0 (by default Jekyll excludes node_modules)\ncat _config.yml\nsass:\n load_paths:\n - _sass\n - node_modules\n - assets\/css\nexclude: []\nEOFdefault.html Layout\nLets create a pretty simple starter default layout:\ncat _layouts\/default.html\n\tJekyll Getting Started\n\t\t{{ content }}\nEOF main.scss ( CSS )\nIn our _layout\/default.html we\u2019ve told the browser to load css from assets\/css\/main.css, so we better create that:\nfirst create the directory mkdir -p assets\/css.\nNow let\u2019s put some text in the file:\n Note: the file has the extension scss, Jekyll will preprocess the CSS and make a .css file\nyou must include the first two lines \u201c\u2014\u201d, this tells Jekyll to preprocess the file\ncat assets\/css\/main.scss\n---\n---\n@import \"bootstrap\/scss\/bootstrap\";\nEOF index.html ( Your new webpage )\nLet\u2019s create an index.html file.\n Note: include the frontmatter, the first 4 lines\nThis tells Jekyll the layout to use (default.html) and gives the page a title (used in the above layout).\ncat index.html\n---\nlayout: default\ntitle: Pauls new site\n---\nMy new site\nEOF Jekyll build and server\nwe\u2019re done! Let\u2019s build the site, then serve it using the inbuilt Jekyll server:jekyll build && jekyll serve --host=0.0.0.0\nAdvanced CSS\nUsing inline CSS\nI like to \u201cinline\u201d my CSS, rather than include a css file.\nIt\u2019s pretty easy to tell Jekyll to inline the CSS.\nLet\u2019s make an _includes directory mkdir _includes.\nNow let\u2019s populate a css file in the includes directory:\n Note: the file extension is .css\nthis file has no frontmatter\ncat _includes\/main.css\n@import \"bootstrap\/scss\/bootstrap\";\nEOFWe don\u2019t need the old file anymore so let\u2019s remove it rm assets\/css\/main.scss.\nfinally, in your _layouts\/default.html replace the css line with:\n{% capture styles %}\n {% include main.css %}\n {% endcapture %}\n {{ styles | scssify }}\n We\u2019re done! Let\u2019s build and serve:jekyll build && jekyll serve --host=0.0.0.0\nCompressing (Minify ) CSS\nIf you\u2019re like me and like to have the fastest possible website, you\u2019re going to want to minify your css\nThat\u2019s super easy too! Just add a small config to your _config.yml :\ncat _config.yml\nsass:\n load_paths:\n - _sass\n - node_modules\n - assets\/css\n style: compressed\nexclude: []\nEOFWe\u2019re done! Let\u2019s build and serve:jekyll build && jekyll serve --host=0.0.0.0\nOpen your browser and check out the source code the Jekyll produces!\nFinal notes\n\u2013 host ?\nYou may be wondering why I use jekyll serve --host=0.0.0.0?\nWhy do I use that \u2013host bit?\nWell by default Jekyll serves up on localhost, and my development server is remote (i.e. I can\u2019t use localhost).\nI could port forward localhost 4000 to the development server (I mean, I\u2019m probably on it anyway doing development).ssh -L 4000:localhost:4000 development.server.nz\nIncluding node_modules directory ?\nNo, I don\u2019t actually include the entire node_modules directory. I have a build script that shuffles files around into the right place first.\nI put this file in the root of mysite then excute using .\/ctl.sh -b && .\/ctl.sh -s\n#!\/bin\/bash\nVENDOR_DIR=assets\/vendor\/\nNPM=\/usr\/bin\/npm\nJEKYLL=\/home\/paul\/gems\/bin\/jekyll\nBUNDLE=\/home\/paul\/gems\/bin\/bundle\nVERSION=\"2018-10-15 v1.0\"\nShowHelp() {\n SCRIPT_NAME=\"$(basename \"$(test -L \"$0\" && readlink \"$0\" || echo \"$0\")\")\"\n echo \"\n$SCRIPT_NAME version $VERSION\n$SCRIPT_NAME is a small shell script that updates, builds, and serves a local Jekyll project\nit can only take one argument at a time.\nUsage:\n$SCRIPT_NAME [single option]\nOptions\n -h, --help Show this help screen\n -u, --update Update your npm packages ($NPM update && $NPM install)\n -b, --build Build your Jekyll project\n -s, --server start a local Jekyll server ($BUNDLE exec $JEKYLL serve)\n\"\n exit 1\n}\nUpdateNPM() {\n if [ ! -d \"$VENDOR_DIR\" ]; then\n mkdir -p $VENDOR_DIR\n fi\n $NPM update\n $NPM install\n cp node_modules\/jquery\/dist\/jquery.min.js $VENDOR_DIR\n cp node_modules\/jquery\/dist\/jquery.min.map $VENDOR_DIR\n cp node_modules\/popper.js\/dist\/umd\/popper.min.js $VENDOR_DIR\n cp node_modules\/popper.js\/dist\/umd\/popper.min.js.map $VENDOR_DIR\n cp node_modules\/bootstrap\/dist\/js\/bootstrap.min.js $VENDOR_DIR\n cp node_modules\/bootstrap\/dist\/js\/bootstrap.min.js.map $VENDOR_DIR \n $BUNDLE\n}\nBuildBundledJS() {\n cat $VENDOR_DIR\/jquery.min.js "},"20":{"url":"https:\/\/terminaladdict.com\/development\/2018\/11\/06\/Comments-on-blogs-vs-Social-Media.html","title":"Comments On Blogs Vs Social Media","content":" Comments On Blogs Vs Social Media\n Posted on 06 Nov 2018 | Categories:\n development\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nSo I\u2019ve run a blog for years, since 2006. Sometimes I blog about personal adventures, sometimes I share coding and sys admin things, sometimes I just talk rubbish. So this thing has been on my mind for a while Comments\nIt\u2019s so easy to comment on Facebook, Instagram, .\nDevelopers ( like me ) try really really hard to make it easy for people to comment on personal blogs too.\nLook here for an example, it\u2019s simple, there is no sign up, no \u201cconfirm your email address\u201d, simple! Just fill out a form and click submit.\n1There\u2019s no magic in the background either. As of writing this (2018) there are no cookies used on this site, no data collection, no database in the background where I send info to advertisers, nothing. and yet, it\u2019s so difficult to get people to comment on our own websites?\nThe media landscape kinda forces us, as website owners, to share our pages on facebook, twitter, instagram, whatever \u2026 and they (the social media websites) really have captured the \u201ccomments\u201d market.\nFor some reason people just don\u2019t like commenting on a private website, but they have no problem commenting on social media sites?!?!?\nThe problem\nSo, the problem from a website owners point of view is - success breeds success. and showing that you\u2019re successful is important to give your website credibility. If people see that others have commented, then they are more comfortable commenting.\nBut if that comment is on another social media site they don\u2019t see it on the private website. :( sad face\nAlso there is a Google search problem.\nGoogle is by far the largest search engine in the world. Most people find my websites through Google. BUT if your comment is on another social media site, Google doesn\u2019t see it, that means Google thinks \u201cGee this site is inactive, I\u2019ll stop recommending it to people\u201d. :( bigger sad face\nThe solution\nWell, I\u2019m not sure. People need to trust a website, trust that it\u2019s OK, that the website owner is not going to sell their details to some advertiser, or use their email address to spam.\nThen, the whole world needs to shift their ideas of how to interact with other people online.\nFacebook is dying, like actually .. fewer and fewer people use it. They\u2019re sick of the advertising, the \u201cshare this if you agree\u201d bollocks, the whole thing has just turned into a mess. Photo sharing like instagram has become popular (instagram is owned by facebook, so they\u2019re probably selling your details like they always have) but it is no good for text blogging; Should we go back to the old fashioned days of visiting people. :)\nCall in for a cuppa\nBack in the bad old days, you used to call in to see your friends, share a cup of coffee, catch up, then do it all again in two weeks.\nDo we go back to that idea? \u201cI\u2019ll just call into TerminalAddict.com and have a cuppa\u201d :)\nSounds ridiculous, but maybe that\u2019s just what\u2019s needed ? Who knows?\nI\u2019d love to hear your thoughts .. leave a comment :D\n I do use google analytics to track visits to my website .. but that\u2019s it.\u00a0\u21a9\n Comments\n\t\tShane\n November 05, 2018 at 11:51 PM\n The best way I\u2019ve found to do it is to repost it on Facebook\/whatever and scrape the comments then reproduce them on your site. Then you have link to the original comment (seeing as it\u2019s not the original attributing the source is good practice). Unfortunately, then you have people saying \u201cI never posted on that site WTF??\u201d.\n\t\tHelen\n November 07, 2018 at 12:18 AM\n Inspired by your blog, I commented on a blog I subscribe to for the first time ever today - on their website :)\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"21":{"url":"https:\/\/terminaladdict.com\/development\/2019\/02\/25\/Web-Development-and-Validation.html","title":"Web Development And Validation","content":" Web Development And Validation\n Posted on 25 Feb 2019 | Categories:\n development\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nSo I do a bit of web development, and of course have developed all 3 my own sites numerous times. I\u2019m currently using Jekyll for my own sites (TerminalAddict.com, Loudas.com, and Paulwillard.nz), you can read about it here: Jekyll Getting Started. \nI want to talk about validation.\nNot all web browser are equal\nThis is straight from the w3 website:\n While contemporary Web browsers do an increasingly good job of parsing even the worst HTML \u201ctag soup\u201d, some errors are not always caught gracefully. Very often, different software on different platforms will not handle errors in a similar fashion, making it extremely difficult to apply style or layout consistently. \nUsing standard, interoperable markup and stylesheets, on the other hand, offers a much greater chance of having one\u2019s page handled consistently across platforms and user-agents. Indeed, most developers creating rich Web applications know that reliable scripting needs the document to be parsed by User-Agents without any unexpected error, and will make sure that their markup and CSS is validated before creating a rich interactive layer. \nWhen surveyed, a large majority of Web professionals will state that validation errors is the first thing they will check whenever they run into a Web styling or scripting bug. \nBasically, all browsers suck somehow. None of them do the right things, and they are always arguing about who is doing it right, and who is doing it wrong; boring !!\nWhat I do\nI try to write valid code ! It\u2019s really simple.\nSimple things like closing all your tags, creating valid headers, using & instead of &.\nI use a few tools to check my work:\nHTML Validator Chrome extension: Link here\nThis little tool installs as part of the Chrome developer tools, and is a simple, quick test, of whether you\u2019ve produced valid html.\nThis tool uses HTML-Tidy in the background. 1\nThe w3c validator: Link here\nThis is a fantastic tool, but interestingly, returns different results to the previous mentioned tool; it must use a different validation tool, or whatever.\nAbsolutely use this during development, and before signing off as complete, on any web project. 2\nThe Structure Data testing tool: Link here\nHere\u2019s a quote from Google:\n Google Search works hard to understand the content of a page. You can help us by providing explicit clues about the meaning of a page to Google by including structured data on the page.\nSo Structured Data lets you define and describe your website data. I use this extensively at Loudas.com, as the data is \u201cbloggy\u201d, and it\u2019s used fairly heavily here too.\nChrome \u201cLighthouse test\u201d\nIn the Chrome developer tools there is a tab titled \u201cAudits\u201d. This uses a chrome tool called lighthouse.\nThis is awesome! Not only does it test validity of your website, but also suggested ways to make your website faster.\nChallenge yourself to see if you can get 100% across all tests. But here\u2019s a warning, you\u2019re going to learn about 3ServiceWorkers if you don\u2019t already know about them.\nThe Benefits\nWell this is also simple; things tend to work better when they\u2019re using a standard.\nYou\u2019ll likely come across less browser based bugs. But as I mentioned earlier, all browsers suck, so the key word here is likely :)\nPlus, you can gloat on forums about how awesome your website is, and how somebody elses is rubbish.\nActually, don\u2019t do that last one, instead just send them this link, and say something like \u201cbro, want some help?\u201d.\nConclusion\nDo better work that meets standards :) there are heaps of tools to help you out along the way.\nGot some cool tools you use? Drop me a comment and let me know.\n The HTML Validator extension has started causing an error in the console: Unchecked runtime.lastError: The message port closed before a response was received.\u00a0\u21a9\n Some of my \u201cpaid\u201d work is terrible ! The customers don\u2019t seem to value validation, and therefore won\u2019t pay for my time to work through errors in their web apps (read: Wordpress installs).\u00a0\u21a9\n I use Google Chrome - Workbox as my ServiceWorker, you can read through my source to see how I use it.\u00a0\u21a9\n Comments\n\t\tWarren\n February 25, 2019 at 03:55 AM\n Yea yea yea \u2026 what about DNS \ud83e\udd14\n\t\tPaul\n October 08, 2019 at 03:20 AM\n I forgot to mentionGoogle PageSpeed\n\t\tPaul\n September 18, 2020 at 10:21 PM\n I\u2019ve changed from Google Structured Data test to https:\/\/github.com\/glitchdigital\/structured-data-testing-tool \nUsage: sdtt --url https:\/\/terminaladdict.com --presets Google,SocialMedia -i \nInstall using: sudo npm i structured-data-testing-tool -g \nOf course you have to have Nodejs installed first\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"22":{"url":"https:\/\/terminaladdict.com\/linux\/2019\/03\/11\/linux-streaming-webcams.html","title":"Linux Streaming Webcams","content":" Linux Streaming Webcams\n Posted on 11 Mar 2019 | Categories:\n linux\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nIn this little snippet \/ howto I\u2019m going to show how I got a regular Logitech webcam streaming over the internet.\nSo let\u2019s start with the problem:\nI have a fishtank, I wanted to create a \u201cfish cam\u201d :)\nStep 1 - Hardware\nSo I have a regular Logitech HD Webcam C910, and a standard Debian stretch sitting on a PC next to my fishtank.\nPretty straight forward so far, I do have contrib and non-free repos enabled\ndeb http:\/\/deb.debian.org\/debian\/ stretch main non-free contrib\ndeb-src http:\/\/deb.debian.org\/debian\/ stretch main non-free contrib\ndeb http:\/\/security.debian.org\/debian-security stretch\/updates main contrib non-free\ndeb-src http:\/\/security.debian.org\/debian-security stretch\/updates main contrib non-freeStep 2 - The streaming software\nMotion - link\nHere\u2019s a wee quote from the website\n Motion is a highly configurable program that monitors video signals from many types of cameras.\nSet it up to monitor your security cameras, watch birds, check in on your pet, create timelapse videos and more.\nWow, that\u2019s what I want to do - check in on my pets :)\nSo let\u2019s install it:\naptitude install motionTADA !!!!\nNo let\u2019s configure it.\nI don\u2019t want to keep images, I just want to stream, so the steps I need to do are:\nCreate a conf directory in my home directory\n Create a config file in the created config directory\nSo let\u2019s create a directory by doingmkdir ~\/.motion\nNo let\u2019s create a config file by doingvi ~\/.motion\/motion.conf\nNote: probably don\u2019t do this as user root\nLet\u2019s look at my config\nstream_port 9091\nstream_localhost off\nwebcontrol_localhost off\nwebcontrol_port 9092\nminimum_motion_frames 1\noutput_pictures off\nquality 100\nstream_quality 100Basically, the needed bits are stream_port 9091, stream_localhost off, and output_pictures off.\nThis sets the tcp port you want to use, disables \u201clocalhost\u201d only, and turns off saving images.\nRun the server\nHere\u2019s the fun bit.motion\nThat\u2019s it, you have a streaming server up and running. You can view it by open a browser and going to http:\/\/your.ip.address:9091\/\nWrapping up\nSo to get this all up and running (and public if you want that) you have to open a tcp port on your firewall.\nI use Mikrotik, so here is what I do:\n\/ip firewall nat\nchain=dstnat action=dst-nat to-addresses=10.0.0.2 to-ports=9091 protocol=tcp in-interface=ether1 dst-port=9091 log=no log-prefix=\"\"and of course you want to see it running, so here\u2019s a link:Fishcam (webcam streaming)\nA wee note: I built a small php proxy script that looks like this:\n Comments\n\t\tPhilip Rhoades\n December 19, 2019 at 11:32 PM\n I use Fedora stuff but I will give this a shot when I get a chance!\nThanks!\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"23":{"url":"https:\/\/terminaladdict.com\/linux\/bash\/golang\/2019\/09\/10\/Install-Golang-on-Debian-Buster.html","title":"Install Golang On Debian Buster","content":" Install Golang On Debian Buster\n Posted on 10 Sep 2019 | Categories:\n linux,\n bash,\n golang\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nGolang, or just simply Go is an open source programming language that makes it easy to build simple, reliable, and efficient software.\nThis is way easier than you think !!\nStep 1 - download\nFirstly, let make sure our system is up-to-datesudo apt update && sudo apt upgrade\nNo let\u2019s download the go package:\nGo to Go\u2019s download page and grab a link for the latest version.\nThe version when I wrote this wee blog was go1.13. \nGot the link? sweet! let\u2019s download it:wget https:\/\/dl.google.com\/go\/go1.13.linux-amd64.tar.gz\nNow let\u2019s untar ittar xvfz go1.13.linux-amd64.tar.gz\nAnd move it to an appropriate place (like \/usr\/local maybe?)sudo mv go \/usr\/local\/go\nStep 2 - setup your environment\nWe\u2019re going to add a few environment variables in our .bashrc, and add to our $PATH.\nso let\u2019s do that\ncat > ~\/.bashrc\nexport GOROOT=\/usr\/local\/go\nexport GOPATH=$HOME\/goProjects\nexport PATH=$GOPATH\/bin:$GOROOT\/bin:$PATH\nEOFand then create our goProjects directory:mkdir ~\/goProjects \nand finally, let\u2019s reload our environment:source ~\/.bashrc \nWhat we\u2019ve done is:\nTold our bash environment where to find go\n Told our bash environment where our working directory is (~\/goProjects)\n added two directories to our $PATH\nStep 3 - verify your install\nHere comes the easy bit, let\u2019s check our installed go version:go version \ngo version go1.13 linux\/amd64and let\u2019s check our go environmentgo env\nGO111MODULE=\"\"\nGOARCH=\"amd64\"\nGOBIN=\"\"\nGOCACHE=\"\/home\/paul\/.cache\/go-build\"\nGOENV=\"\/home\/paul\/.config\/go\/env\"\nGOEXE=\"\"\nGOFLAGS=\"\"\nGOHOSTARCH=\"amd64\"\nGOHOSTOS=\"linux\"\nGONOPROXY=\"\"\nGONOSUMDB=\"\"\nGOOS=\"linux\"\nGOPATH=\"\/home\/paul\/goProjects\"\nGOPRIVATE=\"\"\nGOPROXY=\"https:\/\/proxy.golang.org,direct\"\nGOROOT=\"\/usr\/local\/go\"\nGOSUMDB=\"sum.golang.org\"\nGOTMPDIR=\"\"\nGOTOOLDIR=\"\/usr\/local\/go\/pkg\/tool\/linux_amd64\"\nGCCGO=\"gccgo\"\nAR=\"ar\"\nCC=\"gcc\"\nCXX=\"g++\"\nCGO_ENABLED=\"1\"\nGOMOD=\"\"\nCGO_CFLAGS=\"-g -O2\"\nCGO_CPPFLAGS=\"\"\nCGO_CXXFLAGS=\"-g -O2\"\nCGO_FFLAGS=\"-g -O2\"\nCGO_LDFLAGS=\"-g -O2\"\nPKG_CONFIG=\"pkg-config\"\nGOGCCFLAGS=\"-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=\/tmp\/go-build934234536=\/tmp\/go-build -gno-record-gcc-switches\"Conclusion\nSimple eh? \ud83d\udc4d\nno get \u201cgo-ing\u201d \ud83d\ude02\n Comments\n\t\tDavid Roskams\n December 27, 2019 at 12:59 PM\n Guess it should be:\ncat \u00ab\u00a0\u2018EOF\u2019\u00a0\u00bb ~\/.bashrc\nWithout the quotes variables in the here-doc are interpolated \u2026\n\t\tPaul\n February 08, 2020 at 06:48 AM\n Thanks David, code corrected :)\n\t\tSteve Stonebraker\n May 05, 2020 at 01:11 PM\n Thank you this was super helpful and easy to follow. I used these instructions to set up a go environment on kali linux without any issues.\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"24":{"url":"https:\/\/terminaladdict.com\/networking\/linux\/2019\/09\/13\/DoH.html","title":"Dns Over Https Or (doh) Bind9 And Nginx","content":" Dns Over Https Or (doh) Bind9 And Nginx\n Posted on 13 Sep 2019 | Categories:\n networking,\n linux\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nSo in a litte while Google Chrome is going to enable DNS over HTTPs, and Firefox has already enabled it, by default!\nSo I think to myself \u201cmyself, do you want cloudflare watching all your DNS queries?\u201d - nope is the the answer!\nRight, so I\u2019ll build my own DNS over HTTPs (DoH) server.\nSo what I\u2019m going to do is:\nSetup nginx to act as a front end proxy.\n Build and install a go package called doh-server\n Check that it all works \ud83d\udc68\u200d\ud83d\udcbb\n Configure my browser\nThis doc assumes you have a working DNS server (I use bind9), and you can sort your own SSL certs for nginx.\nIt also assumes you know your way around a command line \ud83e\udd2a\nSet up nginx\nSo I\u2019m not going to talk you through how to install nginx, or get it running, that is beyond the scope of this doc.\nI\u2019m also not going to tell you how to setup Let\u2019s Encrypt, that is also outside the scope of this doc.\nSo let\u2019s get straight into the config:\nupstream dns-backend {\n server 127.0.0.1:8053;\n keepalive 30;\n}\nserver {\n listen 80;\n listen [::]:80;\n location \/.well-known\/acme-challenge {\n alias \/var\/www\/dehydrated;\n }\n root \/var\/www\/html;\n server_name ns1.example.com;\n return 301 https:\/\/$host;\n}\nserver {\n listen 443 ssl http2;\n listen [::]:443 ssl http2;\n location \/.well-known\/acme-challenge {\n alias \/var\/www\/dehydrated;\n }\n ssl_certificate \/etc\/dehydrated\/certs\/ns1.example.com\/fullchain.pem;\n ssl_certificate_key \/etc\/dehydrated\/certs\/ns1.example.com\/privkey.pem;\n # enables all versions of TLS, but not SSLv2 or 3 which are weak and now deprecated.\n ssl_protocols TLSv1 TLSv1.1 TLSv1.2;\n # disables all weak ciphers\n ssl_ciphers 'AES128+EECDH:AES128+EDH';\n ssl_prefer_server_ciphers on;\n root \/var\/www\/html;\n index index.html index.htm index.nginx-debian.html;\n server_name ns1.example.com;\n access_log \/var\/log\/nginx\/ns1.example.com-access.log;\n error_log \/var\/log\/nginx\/ns1.example.com-error.log;\n location \/dns-query {\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header Host $http_host;\n proxy_set_header X-NginX-Proxy true;\n proxy_set_header Connection \"\";\n proxy_http_version 1.1;\n proxy_set_header Upgrade $http_upgrade;\n proxy_redirect off;\n proxy_set_header X-Forwarded-Proto $scheme;\n proxy_read_timeout 86400;\n proxy_pass http:\/\/dns-backend\/dns-query;\n }\n}So let me talk you through the config:\nI start by creating a config that points to our, not yet installed, doh-server. That server is going to be running on port 8053:\nupstream dns-backend {\n server 127.0.0.1:8053;\n keepalive 30;\n}Next I\u2019ve got a server block for port 80 (non-secure \/ non https).\nIt has some config for my Let\u2019s Encrypt SSL cert bot (dehydrated), and redirects everthing to the SSL version of the website (return 301):\nserver {\n listen 80;\n listen [::]:80;\n location \/.well-known\/acme-challenge {\n alias \/var\/www\/dehydrated;\n }\n root \/var\/www\/html;\n server_name ns1.example.com;\n return 301 https:\/\/$host;\n}and lastly, the SSL version config, includng the reverse proxy bit which I will repeat here (because it is the important bit):\nlocation \/dns-query {\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header Host $http_host;\n proxy_set_header X-NginX-Proxy true;\n proxy_set_header Connection \"\";\n proxy_http_version 1.1;\n proxy_set_header Upgrade $http_upgrade;\n proxy_redirect off;\n proxy_set_header X-Forwarded-Proto $scheme;\n proxy_read_timeout 86400;\n proxy_pass http:\/\/dns-backend\/dns-query;\n}So assuming that you have your SSL certs sorted, and your nginx config is all good you should be able to start nginx \ud83e\udd70\nInstall doh-server\nso you\u2019ll need some build packages, so let\u2019s install some build tools:aptitude install curl software-properties-common build-essential git\nAnd you\u2019re going to need to get your golang environment setup:Install Go on Debian Buster\nnow let\u2019s install the DoH server:\ngit clone git@github.com:m13253\/dns-over-https.git\ncd dns-over-https\/\nmake\nmake installNow let\u2019s config the DoH server:\nThe DoH server has a config in \/etc\/dns-over-https\/doh-server.conf\nYou want to change the upstream to use 127.0.0.1:53 and that\u2019s about it, here\u2019s what I\u2019ve got:\nlisten = [\n \"127.0.0.1:8053\",\n \"[::1]:8053\"\n]\nlocal_addr = \"\"\ncert = \"\"\nkey = \"\"\npath = \"\/dns-query\"\nupstream = [\n\t\"127.0.0.1:53\"\n]\ntimeout = 10\ntries = 3\ntcp_only = false\nverbose = false\nlog_guessed_client_ip = falseOnce you\u2019ve got that saved you can restart the DoH server with systemctl restart doh-server\nTesting the install\nSo let\u2019s recap:\nWe have:\nConfigured nginx and got it running nicely, forwarding DoH requests\n Installed a DoH server\n We already had a DNS resolver installed and running, right? \ud83e\uddd0\nNow let\u2019s do some testing.\nThe DoH server returns JSON, so you can just test in your browser:\nhttps:\/\/ns1.example.com\/dns-query?name=example.org&type=A\nOr, since you\u2019re already working in a terminal (and this website is called Terminal Addict \ud83d\ude07)\ncurl -s \"https:\/\/ns1.example.com\/dns-query?name=example.org&type=A\" | python -m json.toolYou should get a JSON response like the following:\n{\n \"AD\": true,\n \"Answer\": [\n {\n \"Expires\": \"Thu, 12 Sep 2019 22:59:07 UTC\",\n \"TTL\": 7090,\n \"data\": \"93.184.216.34\",\n \"name\": \"example.org.\",\n \"type\": 1\n },\n {\n \"Expires\": \"Thu, 12 Sep 2019 22:59:07 UTC\",\n \"TTL\": 7090,\n \"data\": \"A 8 2 86400 20190921055451 20190831145703 31036 example.org. r4fWzdiYS7Px0qXX+7cHtPsj2a3lFhmeM4OXvOsDd2WorpP3Na\/FupUFozdp2ao7xyguW+tZSJEI01dKuMt5MDfmJR4cN2n+IiRMvLvQuG60SnQNRBmOTTwca79GNTv5To8rxU5kSixH1liyho2\/c\/hvIqZKajHs6Bxr460A\/RM=\",\n \"name\": \"example.org.\",\n \"type\": 46\n }\n ],\n \"Authority\": [\n {\n \"Expires\": \"Thu, 12 Sep 2019 21:18:35 UTC\",\n \"TTL\": 1058,\n \"data\": \"l.root-servers.net.\",\n \"name\": \".\",\n \"type\": 2\n },\n {\n \"Expires\": \"Thu, 12 Sep 2019 21:18:35 UTC\",\n \"TTL\": 1058,\n \"data\": \"j.root-servers.net.\",\n \"name\": \".\",\n \"type\": 2\n },\n {\n \"Expires\": \"Thu, 12 Sep 2019 21:18:35 UTC\",\n \"TTL\": 1058,\n \"data\": \"h.root-servers.net.\",\n \"name\": \".\",\n \"type\": 2\n },\n {\n \"Expires\": \"Thu, 12 Sep 2019 21:18:35 UTC\",\n \"TTL\": 1058,\n \"data\": \"e.root-servers.net.\",\n \"name\": \".\",\n \"type\": 2\n },\n {\n \"Expires\": \"Thu, 12 Sep 2019 21:18:35 UTC\",\n \"TTL\": 1058,\n \"data\": \"f.root-servers.net.\",\n \"name\": \".\",\n \"type\": 2\n },\n {\n \"Expires\": \"Thu, 12 Sep 2019 21:18:35 UTC\",\n \"TTL\": 1058,\n \"data\": \"g.root-servers.net.\",\n \"name\": \".\",\n \"type\": 2\n },\n {\n \"Expires\": \"Thu, 12 Sep 2019 21:18:35 UTC\",\n \"TTL\": 1058,\n \"data\": \"k.root-servers.net.\",\n \"name\": \".\",\n \"type\": 2\n },\n {\n \"Expires\": \"Thu, 12 Sep 2019 21:18:35 UTC\",\n \"TTL\": 1058,\n \"data\": \"b.root-servers.net.\",\n \"name\": \".\",\n \"type\": 2\n },\n {\n \"Expires\": \"Thu, 12 Sep 2019 21:18:35 UTC\",\n \"TTL\": 1058,\n \"data\": \"d.root-servers.net.\",\n \"name\": \".\",\n \"type\": 2\n },\n {\n \"Expires\": \"Thu, 12 Sep 2019 21:18:35 UTC\",\n \"TTL\": 1058,\n \"data\": \"i.root-servers.net.\",\n \"name\": \".\",\n \"type\": 2\n },\n {\n \"Expires\": \"Thu, 12 Sep 2019 21:18:35 UTC\",\n \"TTL\": 1058,\n \"data\": \"a.root-servers.net.\",\n \"name\": \".\",\n \"type\": 2\n },\n {\n \"Expires\": \"Thu, 12 Sep 2019 21:18:35 UTC\",\n \"TTL\": 1058,\n \"data\": \"m.root-servers.net.\",\n \"name\": \".\",\n \"type\": 2\n },\n {\n \"Expires\": \"Thu, 12 Sep 2019 21:18:35 UTC\",\n \"TTL\": 1058,\n \"data\": \"c.root-servers.net.\",\n \"name\": \".\",\n \"type\": 2\n },\n {\n \"Expires\": \"Thu, 12 Sep 2019 21:18:35 UTC\",\n \"TTL\": 1058,\n \"data\": \"NS 8 0 518400 20190925170000 20190912160000 59944 . E7Vt9bijsTA8J2m5mcI9mc7uyk2PAbjtuDS4zGFaDVpVP4UyFFPYrttCA5CrXFurVN+Qf0nzB31pLzPfrgnY2xqe2S0Pm7Qq+t7rCp\/Q1mNp3JbZG4fYxRXoz9uz4zSCaXDJ9WP4zrWrYd++ZGuUs4DXawg9qo0QhX5KRnXehDM9WkjY3JM61tw8CN5KS1ODov7Nw5qZI2uJ69npPnElm163cePQgZTkoGA8AO5vgmgHVbZZqQ3GkxNa8lzHNH\/G66xEvPXLe03h6QptCHcOugU6SwCzmxbt2hQnvbQXZk4eGz330CmwlwVPEAKP3VwWsruEkU+LWBIohDg\/0Yk6Dg==\",\n \"name\": \".\",\n \"type\": 46\n }\n ],\n \"CD\": false,\n \"Question\": [\n {\n \"name\": \"example.org.\",\n \"type\": 1\n }\n ],\n \"RA\": true,\n \"RD\": true,\n \"Status\": 0,\n \"TC\": false,\n \"edns_client_subnet\": \"103.123.164.0\/0\"\n}Configure your browser\nWell in Firefox this is pretty easy.\nSearch your preferences \/ settings in Firefox for DNS.\nIn Google Chrome the setting will be released in version 78 I\u2019m told, I guess I\u2019ll keep an eye out \ud83d\ude43\nConclusion\nSo, maybe you\u2019re super sentive about people spying on you, maybe you like playing with new gadgets \/ tech. Who knows.\nBut, I certainly don\u2019t trust cloudflare enough to be giving them my browser DNS queries!\nSo we\u2019ve now got DNS over HTTPs to use, and we own all our own history \/ data \ud83d\udc4d\n Comments\n\t\tPaul\n September 12, 2019 at 09:39 PM\n If you are interested as a user in \u201cjust using a private DNS server\u201d and not building you own, let me know.\nI might build a public facing DoH server for people to use.\n\t\tHanif Ayala\n February 12, 2020 at 04:11 AM\n how you set up your lets encrypt?\n\t\tPaul\n February 12, 2020 at 10:44 PM\n Hi Hanif,\nI\u2019ve created a blog today about Lets Encrypt\nHope that helps.\n\t\tMichael Newton\n February 25, 2020 at 05:07 PM\n Nice article, I have 2 questions. Do clients support authentication? Like, assuming Nginx was set up for HTTP basic auth, could I use a full URL like https:\/\/user:password@host\/ in the Firefox preferences above? Which brings me to my second question, is there a need for Nginx in this setup? Assuming you aren\u2019t already running a web server on 443 of course, it seems like the DoH server can listen directly for requests.\n\t\tPaul\n February 25, 2020 at 07:32 PM\n Hi Michael,\ngood questions.\nSo after 5 seconds of testing, it looks like Firefox does support HTTP basic auth, so yes, you could configure your DNS server as user:pass@ns1.example.com\nThe need for Nginx is to server SSL certs (HTTPS); you could use anything (maybe write your own Go web service? or fork the DoH server and add in SSL support), so long as it has the ability to 1) reverse proxy to the DoH server, and 2) server SSL certificates, or 3) write a new DoH server that supports SSL \ud83d\ude00\nThis DoH server doesn\u2019t have the ability to communicate via SSL.\n\t\tMichael Newton\n February 25, 2020 at 10:28 PM\n I assumed from the config entries cert and key that the DNS-over-HTTPS server would serve TLS. The code would appear to back me up but I\u2019ll have to try an installation before I can say for sure.\n\t\tPaul\n February 25, 2020 at 10:43 PM\n You could be right !!!\nI might do some testing myself !\nI\u2019d also have to figure out how to do Let\u2019s Encrypt without Nginx as well\n\t\tHanif\n March 02, 2020 at 09:02 AM\n thanks for your help, im doing research for my final exam about DoH\n\t\tAdib\n April 03, 2020 at 02:55 AM\n Hi Paul, thanks for writing this.\nWhy do you need for a \u201cpackage\u201d dns-over-https? Because I think that \u201cthe dns-query\u201d from nginx can head straight to Bind9. Could you explain this more plase? \nThankyou.\n\t\tPaul\n April 03, 2020 at 03:13 AM\n Hi,\nyou need the doh server to interpret between a DNS conversation, and a http conversation.\nThe doh server returns JSON to nginx.\nSo you need nginx for SSL and http conversation (although you may not, as Michael points out above)\nyou need the DoH server as an interpreter between http and dns.\nand you need bind (or some other) dns server.\n\t\tAmos Rosenboim\n July 08, 2020 at 07:08 AM\n Scale question \nFirst, thanks for the nice post, well written \nTo what scale have you been able to test this ?\n\t\tPaul\n July 08, 2020 at 10:41 AM\n Hey Amos, this doesn\u2019t seem to consume a lot of resources. I haven\u2019t tested within an ISP environ yet, only within say 50-100 desktops\n\t\tWonyoung Park\n August 13, 2020 at 05:09 AM\n Hi Paul, i tried DoH configuration by following your document, but it didn\u2019t work when i tested in firefox, but it worked in curl. do you have any ideas? thanks.\n\t\tPaul\n August 15, 2020 at 10:32 PM\n Hi Wonyoung, how did you confirm it was working in Firefox?\nI can see in my nginx logs queries happening, and things working as expected?\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"25":{"url":"https:\/\/terminaladdict.com\/linux\/networking\/bash\/2020\/02\/13\/LetsEncrypt.html","title":"Lets Encrypt Setup On Debian","content":" Lets Encrypt Setup On Debian\n Posted on 13 Feb 2020 | Categories:\n linux,\n networking,\n bash\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nSo in a few of my posts I\u2019ve mentioned Let\u2019s Encrypt as a method of getting SSL Certificates for free.\nIn this post I\u2019ll explain how I set up Nginx to use Let\u2019s Encrypt SSL certs.\nInitial install and setup\nI decide a while ago that Dehydrated would be the script I would use to manage my SSL certs. And conveniently for me there is a Debian package. So let\u2019s install it.\naptitude install dehydrated\nThis creates a config directory in \/etc\/dehydrated and stores all your certs in \/var\/lib\/dehydrated\/certs.\nGreat, let\u2019s config it.\n#############################################################\n# This is the main config file for dehydrated #\n# #\n# This is the default configuration for the Debian package. #\n# To see a more comprehensive example, see #\n# \/usr\/share\/doc\/dehydrated\/examples\/config #\n# #\n# For details please read: #\n# \/usr\/share\/doc\/dehydrated\/README.Debian #\n#############################################################\nCONFIG_D=\/etc\/dehydrated\/conf.d\nBASEDIR=\/var\/lib\/dehydrated\nWELLKNOWN=\"\/var\/www\/dehydrated\"\nDOMAINS_TXT=\"\/etc\/dehydrated\/domains.txt\"\nCONTACT_EMAIL=paul@domain.com\nHOOK=\/etc\/dehydrated\/hook.shOk, so there\u2019s a few things in this config we\u2019re going to have to create\nthe directory \/var\/www\/dehydrated\n the file \/etc\/dehydrated\/domains.txt\n the hook file \/etc\/dehydrated\/hook.sh\nSo let\u2019s do that:\nmkdir \/var\/www\/dehydrated && chown www-data:www-data \/var\/www\/dehydrated\nPretty simple so far.\nThe domains file\nterminaladdict.com www.terminaladdict.com myother-subdomain.terminaladdict.comLet\u2019s Encrypt creates one certificate \u201cper line\u201d i.e. it creates one certificate that covers the domain terminaladdict.com, and the sub domains.\nThe sub domains must all exist in DNS, and all exist in Nginx.\nThe Hook File\nI got this hook file from Antoine Aflalo \nHere it is:\ndeploy_challenge() {\n local DOMAIN=\"${1}\" TOKEN_FILENAME=\"${2}\" TOKEN_VALUE=\"${3}\"\n}\nclean_challenge() {\n local DOMAIN=\"${1}\" TOKEN_FILENAME=\"${2}\" TOKEN_VALUE=\"${3}\"\n}\ndeploy_cert() {\n local DOMAIN=\"${1}\" KEYFILE=\"${2}\" CERTFILE=\"${3}\" FULLCHAINFILE=\"${4}\" CHAINFILE=\"${5}\" TIMESTAMP=\"${6}\"\n systemctl reload nginx\n}\nunchanged_cert() {\n local DOMAIN=\"${1}\" KEYFILE=\"${2}\" CERTFILE=\"${3}\" FULLCHAINFILE=\"${4}\" CHAINFILE=\"${5}\"\n}\ninvalid_challenge() {\n local DOMAIN=\"${1}\" RESPONSE=\"${2}\"\n}\nrequest_failure() {\n local STATUSCODE=\"${1}\" REASON=\"${2}\" REQTYPE=\"${3}\"\n}\nexit_hook() {\n :\n}\nHANDLER=\"$1\"; shift\nif [[ \"${HANDLER}\" =~ ^(deploy_challenge|clean_challenge|deploy_cert|unchanged_cert|invalid_challenge|request_failure|exit_hook)$ ]]; then\n \"$HANDLER\" \"$@\"\nfiNginx Config\nSetting up Nginx is pretty straight forward, you need a \u201c.well-known\u201d directive:\nserver {\n listen 80;\n listen [::]:80;\n location \/.well-known\/acme-challenge {\n alias \/var\/www\/dehydrated;\n }\n root \/var\/www\/html\/terminaladdict.com;\n server_name terminaladdict.com www.terminaladdict.com;\n}that\u2019s our entire config for port 80 (HTTP).\nFor the SSL port 443 (HTTPS) config:\nserver {\n\tlisten 443 ssl http2;\n\tlisten [::]:443 ssl http2;\n location \/.well-known\/acme-challenge {\n alias \/var\/www\/dehydrated;\n }\n ssl_certificate \/var\/lib\/dehydrated\/certs\/terminaladdict.com\/fullchain.pem;\n ssl_certificate_key \/var\/lib\/dehydrated\/certs\/terminaladdict.com\/privkey.pem;\n\t# enables all versions of TLS, but not SSLv2 or 3 which are weak and now deprecated.\n ssl_protocols TLSv1 TLSv1.1 TLSv1.2;\n # disables all weak ciphers\n ssl_ciphers 'AES128+EECDH:AES128+EDH';\n ssl_prefer_server_ciphers on;\n root \/var\/www\/html\/terminaladdict.com;\n client_max_body_size 100m;\n index index.html;\n server_name terminaladdict.com;\n access_log \/var\/log\/nginx\/terminaladdict.com-access.log;\n error_log \/var\/log\/nginx\/terminaladdict.com-error.log;\n location \/ {\n try_files $uri $uri\/ index.html;\n add_header Service-Worker-Allowed \/;\n }\n error_page 404 =404 \/404.html;\n location \/manifest.json {\n default_type application\/x-web-app-manifest+json;\n }\n location ~ \/\\.ht {\n deny all;\n }\n # ESSENTIAL : no favicon logs\n location = \/favicon.ico {\n log_not_found off;\n access_log off;\n }\n # ESSENTIAL : robots.txt\n location = \/robots.txt {\n allow all;\n log_not_found off;\n access_log off;\n }\n location ~* sw\\.js$ {\n expires -1;\n }\n # PERFORMANCE : Set expires headers for static files and turn off logging.\n location ~* ^.+\\.(js|css|swf|xml|txt|ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {\n access_log off; log_not_found off; expires 30d;\n }\n}You won\u2019t be able to restart Nginx yet, as you don\u2019t have the certs.\nWhat I do is comment out the two lines that point to the certs, reload Nginx, then uncomment them once I have the certs.\nApache Config\nSetting up Apache is pretty straight forward, you need a .well-known directive:\n ServerAdmin paul@paulwillard.nz\n DocumentRoot \/var\/www\/html\/terminaladdict.com\n ErrorLog ${APACHE_LOG_DIR}\/error.log\n CustomLog ${APACHE_LOG_DIR}\/access.log combined\n ServerName terminaladdict.com\n\tServerAlias www.terminaladdict.com\n Alias \/.well-known\/acme-challenge \/var\/www\/dehydrated\n \tOptions None\n \tAllowOverride None\n \t# Apache 2.x\n \t\t allow,deny\n \t\t from all\n \t# Apache 2.4\n \t\t all granted\n \tRedirectMatch 404 \"^(?!\/\\.well-known\/acme-challenge\/[\\w-]{43}$)\"\n RewriteEngine On\n RewriteCond %{REQUEST_URI} !^\/.well-known\/acme-challenge [NC]\n RewriteCond %{HTTPS} off\n RewriteRule (.*) https:\/\/%{HTTP_HOST}%{REQUEST_URI}\nthats our entire config for port 80 (HTTP).\nFor the SSL port 443 (HTTPS) config:\nnotice I have 2 ssl directives, the www directive redirects to the non-www directive.\n ServerAdmin paul@paulwillard.nz\n DocumentRoot \/var\/www\/html\/terminaladdict.com\n ErrorLog ${APACHE_LOG_DIR}\/error.log\n CustomLog ${APACHE_LOG_DIR}\/access.log combined\n ServerName www.terminaladdict.com;\n SSLEngine on\n SSLCertificateFile \/var\/lib\/dehydrated\/certs\/terminaladdict.com\/fullchain.pem\n SSLCertificateKeyFile \/var\/lib\/dehydrated\/certs\/terminaladdict.com\/privkey.pem\n Alias \/.well-known\/acme-challenge \/var\/www\/dehydrated\n Options None\n AllowOverride None\n # Apache 2.x\n allow,deny\n from all\n # Apache 2.4\n all granted\n RedirectMatch 404 \"^(?!\/\\.well-known\/acme-challenge\/[\\w-]{43}$)\"\n RewriteEngine On\n RewriteCond %{REQUEST_URI} !^\/.well-known\/acme-challenge [NC]\n RewriteCond %{HTTPS} off\n RewriteRule (.*) https:\/\/terminaladdict.com%{REQUEST_URI}\n ServerAdmin paul@paulwillard.nz\n DocumentRoot \/var\/www\/html\/terminaladdict.com\n ErrorLog ${APACHE_LOG_DIR}\/error.log\n CustomLog ${APACHE_LOG_DIR}\/access.log combined\n ServerName terminaladdict.com;\n SSLEngine on\n SSLCertificateFile \/var\/lib\/dehydrated\/certs\/terminaladdict.com\/fullchain.pem\n SSLCertificateKeyFile \/var\/lib\/dehydrated\/certs\/terminaladdict.com\/privkey.pem\n SSLOptions +StdEnvVars\n SSLOptions +StdEnvVars\n Alias \/.well-known\/acme-challenge \/var\/www\/dehydrated\n Options None\n AllowOverride None\n # Apache 2.x\n allow,deny\n from all\n # Apache 2.4\n all granted\n RedirectMatch 404 \"^(?!\/\\.well-known\/acme-challenge\/[\\w-]{43}$)\"\n # 2.4.10+ can proxy to unix socket\n SetHandler \"proxy:unix:\/run\/php\/php7.3-fpm.sock|fcgi:\/\/localhost\"\nGetting the cert\nHere we go:dehydrated -fc -c\nYou should see output like this:\nProcessing terminaladdict.com with alternative names: www.terminaladdict.com\n + Checking domain name(s) of existing cert... unchanged.\n + Checking expire date of existing cert...\n + Valid till Mar 12 12:05:56 2020 GMT Certificate will expire\n(Less than 30 days). Renewing!\n + Signing domains...\n + Generating private key...\n + Generating signing request...\n + Requesting new certificate order from CA...\n + Received 2 authorizations URLs from the CA\n + Handling authorization for terminaladdict.com\n + Handling authorization for www.terminaladdict.com\n + 2 pending challenge(s)\n + Deploying challenge tokens...\n + Responding to challenge for terminaladdict.com authorization...\n + Challenge is valid!\n + Responding to challenge for www.terminaladdict.com authorization...\n + Challenge is valid!\n + Cleaning challenge tokens...\n + Requesting certificate...\n + Checking certificate...\n + Done!\n + Creating fullchain.pem...\n + Done!That\u2019s it! go and load your website in a browser and check out your new SSL certificate!\nAutomating\nHello cron:\n# lets encrypt\n5 2 * * 6 root \/usr\/bin\/dehydrated -fc -c > \/dev\/null 2>&1\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"26":{"url":"https:\/\/terminaladdict.com\/php\/networking\/2020\/09\/11\/cctv-streaming-to-a-website.html","title":"Streaming A Zoneminder Monitor To A Web Site","content":" Streaming A Zoneminder Monitor To A Web Site\n Posted on 11 Sep 2020 | Categories:\n php,\n networking\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nSo I run a CCTV system based on the excellent open source Zoneminder, running on a pretty entry level ex-lease PC I bought from PBTech.\nWhat I want to do is embed one of the cameras into a web site.\nSo my steps are going to be:\nSetup a Zoneminder user for public access.\n Write a small PHP proxy script.\n Profit!\nPrerequisites\nI\u2019m not going to talk you through setting up a Debian server.\nNor am I going to talk you through setting up a Zoneminder server on a Debian server.\nI will assume that you have these things running.\nI\u2019ll also assume that you have the Zoneminder console running from a virtual sub directory in Apache (in my case \/zm\/ ).\nBut just in case, here\u2019s a quick reminder of the Apache config:\n# Remember to enable cgi mod (i.e. \"a2enmod cgi\").\nScriptAlias \/zm\/cgi-bin \"\/usr\/lib\/zoneminder\/cgi-bin\"\n Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch\n AllowOverride All\n Require all granted\n# Order matters. This alias must come first.\nAlias \/zm\/cache \/var\/cache\/zoneminder\/cache\n Options -Indexes +FollowSymLinks\n AllowOverride None\n # Apache 2.4\n Require all granted\n # Apache 2.2\n Order deny,allow\n Allow from all\nAlias \/zm \/usr\/share\/zoneminder\/www\n Options -Indexes +FollowSymLinks\n DirectoryIndex index.php\n# For better visibility, the following directives have been migrated from the\n# default .htaccess files included with the CakePHP project.\n# Parameters not set here are inherited from the parent directive above.\n RewriteEngine on\n RewriteRule ^$ app\/webroot\/ [L]\n RewriteRule (.*) app\/webroot\/$1 [L]\n RewriteBase \/zm\/api\n RewriteEngine on\n RewriteRule ^$ webroot\/ [L]\n RewriteRule (.*) webroot\/$1 [L]\n RewriteBase \/zm\/api\n RewriteEngine On\n RewriteCond %{REQUEST_FILENAME} !-d\n RewriteCond %{REQUEST_FILENAME} !-f\n RewriteRule ^ index.php [L]\n RewriteBase \/zm\/api\nZoneminder read only user\nRight, let\u2019s start with a Zoneminder \u201cread only\u201d user.\nIn your Zoneminder console, head to Options->User, and smash that \u201cADD NEW USER\u201d button.\nPretty straight forward:\nUsername = YOURPUBLICUSER\n Password = YOURPUBLICPASS\n Confirm Password = YOURPUBLICPASS\n Language\n Enabled = yes\n Stream = View\n Events = None\n Control = None\n Monitors = View\n Groups = None\n System = None\n Max bandwidth = whatever you like\n Restricted monitors = Select the Cameras you want available publicly.\n API Enabled = No\nSave that bad boy.\nThat\u2019s step 1 done \ud83d\ude0a\nA PHP Proxy script\nSo at this point you could just jam an image in any web site, using a specially crafted URL:http:\/\/YOUR-ZONEMINDER-CCTV-URL\/zm\/cgi-bin\/nph-zms?monitor=1&user=YOURPUBLICUSER&pass=YOURPUBLICPASS\nBut, that kinda exposes, well, everything ! Your CCTV url, your readonly user and pass. I dunno, it just doesn\u2019t seem right to me \ud83e\udd23\nSo, I\u2019m going to craft a small PHP proxy script which will hide this info from public view.\nThat\u2019s it; save that PHP script as .. I dunno .. zoneminder_stream.php ?\nEmbed in HTML\nHere\u2019s the fun bit .. simple HTML !\nand here is the working result:\n*note: this is a screenshot of my working camera\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"27":{"url":"https:\/\/terminaladdict.com\/bash\/networking\/2020\/09\/21\/graphing-speedtest-results.html","title":"Graphing Speedtest Results","content":" Graphing Speedtest Results\n Posted on 21 Sep 2020 | Categories:\n bash,\n networking\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nI can be described as a network engineer, sometimes, and sometimes a system admin. As such, keeping track of how customers internet is working is reasonably important.\nMost customers use Speedtest.net as a way of testing their internet connection, so I figured I would clobber together a script that keeps a bit of history, and make some pretty graphs \ud83d\ude05.\nSo my steps are going to be:\nInstall rrdtool, Gawk, and grep\n Install Ookla speedtest cli.\n Write a bash script to create, update, and graph, some results\n Profit!\nPrerequisites\nI\u2019m not going to talk you through setting up a Linux server.\nI will assume that you have a running server.\nYour linux server can be any flavour you like, I prefer Debian and Ubuntu distros, and I prefer aptitude as a package manager; you can use whatever you like \ud83e\udd17.\nI\u2019m also not going to talk you through setting up a web server .. sort that out yourself \ud83d\ude1c.\nYou NEED unlimited data on your internet!!!!\nLet me say that again .. YOU NEED UNLIMITED DATA ON YOUR INTERNET !!!\n This script will thrash your internet usage!\nInstalling the packages, and setting up directories\nRight, let\u2019s start with installing rrdtool, Gawk, and grepsudo aptitude install rrdtool gawk grep\nThat\u2019s pretty easy !\nInstall Ookla Speedtest cli\nSo you can head over to the Ookla Speedtest cli website and download the appropriate package. In my case it\u2019s the Linux x86_64 package, which is at version 1.0.0.wget https:\/\/bintray.com\/ookla\/download\/download_file?file_path=ookla-speedtest-1.0.0-x86_64-linux.tgz -O \/tmp\/speedtest.tgz\nNow let\u2019s unpack it:tar xvfz \/tmp\/speedtest.tgz -C \/tmp\nAnd put it in a usable spot on the OS:sudo mv \/tmp\/speedtest \/usr\/local\/bin\/speedtest\nRunning Speedtest cli\nThe first time you run speedtest you will be asked to agree to a license:\n\/usr\/local\/bin\/speedtest\n==============================================================================\nYou may only use this Speedtest software and information generated\nfrom it for personal, non-commercial use, through a command line\ninterface on a personal computer. Your use of this software is subject\nto the End User License Agreement, Terms of Use and Privacy Policy at\nthese URLs:\n https:\/\/www.speedtest.net\/about\/eula\n https:\/\/www.speedtest.net\/about\/terms\n https:\/\/www.speedtest.net\/about\/privacy\n==============================================================================\nDo you accept the license? [type YES to accept]:Now you\u2019re ready to go!\nYou can list out the nearest servers like so:\n\/usr\/local\/bin\/speedtest -L\nClosest servers:\n ID Name Location Country\n==============================================================================\n 5469 MyRepublic Limited Auckland New Zealand\n 5749 Vocusgroup NZ Auckland New Zealand\n 11327 Spark New Zealand Auckland New Zealand\n 2720 WorldNet Auckland New Zealand\n 4953 Vodafone New Zealand Auckland New Zealand\n 721 WorldxChange Comm Auckland New Zealand\n 13676 speedtest.nzpbx.com Auckland New Zealand\n 12932 Feenix Communications Limited Auckland New Zealand\n 16805 Nova Energy AUCKLAND New Zealand\n 25477 Devoli Auckland New ZealandThis particular customer I am testing from is connected through Vocus.\nSo I\u2019m going to use Vocus to test against.\n\/usr\/local\/bin\/speedtest -s 5749\n Speedtest by Ookla\n Server: Vocusgroup NZ - Auckland (id = 5749)\n ISP: Vocus Communications\n Latency: 5.10 ms (0.37 ms jitter)\n Download: 844.16 Mbps (data used: 808.7 MB)\n Upload: 548.05 Mbps (data used: 267.4 MB)\nPacket Loss: 0.0%\n Result URL: https:\/\/www.speedtest.net\/result\/c\/1ff5533b-b0de-42c5-bd14-24c299cfc249Sweet !\nCreate a directory\nOk, so now let\u2019s create a directory to store history, and images.sudo mkdir \/var\/www\/html\/rrdsudo chown paul:paul \/var\/www\/html\/rrd\nNote: I have changed the owner of the directory to the user \u2018paul\u2019. Change to whatever user you\u2019re going to be running this script as.\nThe RRD Script\nOk, so here\u2019s where the magic happens. So let\u2019s skip straight to the script:\n#!\/bin\/bash\n# generate a speedtest result\n# 5749 server is Vocus\n\/usr\/local\/bin\/speedtest -s 5749 -p no > \/tmp\/speedtest.txt 2>\/dev\/null\nTRAF=\/var\/www\/html\/rrd\n case $1 in (create)\n \/usr\/bin\/rrdtool create $TRAF\/upload.rrd -s 60 \\\n DS:upload:GAUGE:600:0:U \\\n RRA:AVERAGE:0.5:1:4320 \\\n RRA:AVERAGE:0.5:1440:3 \\\n RRA:MIN:0.5:1440:3 \\\n RRA:MAX:0.5:1440:3\n \/usr\/bin\/rrdtool create $TRAF\/download.rrd -s 60 \\\n DS:download:GAUGE:600:0:U \\\n RRA:AVERAGE:0.5:1:4320 \\\n RRA:AVERAGE:0.5:1440:3 \\\n RRA:MIN:0.5:1440:3 \\\n RRA:MAX:0.5:1440:3\n \/usr\/bin\/rrdtool create $TRAF\/echoreply.rrd -s 60 \\\n DS:echoreply:GAUGE:600:0:U \\\n RRA:AVERAGE:0.5:1:4320 \\\n RRA:AVERAGE:0.5:1440:3 \\\n RRA:MIN:0.5:1440:3 \\\n RRA:MAX:0.5:1440:3\n ;;\n (update)\n \/usr\/bin\/rrdtool update $TRAF\/upload.rrd N:`cat \/tmp\/speedtest.txt | grep Upload | awk '{print $3}'`\n \/usr\/bin\/rrdtool update $TRAF\/download.rrd N:`cat \/tmp\/speedtest.txt | grep Download | awk '{print $3}'`\n \/usr\/bin\/rrdtool update $TRAF\/echoreply.rrd N:`cat \/tmp\/speedtest.txt | grep Latency | awk '{print $2}'`\n ;;\n (graph)\n \/usr\/bin\/rrdtool graph $TRAF\/upload.png \\\n --start \"-3day\" \\\n -c \"BACK#000000\" \\\n -c \"SHADEA#000000\" \\\n -c \"SHADEB#000000\" \\\n -c \"FONT#DDDDDD\" \\\n -c \"CANVAS#202020\" \\\n -c \"GRID#666666\" \\\n -c \"MGRID#AAAAAA\" \\\n -c \"FRAME#202020\" \\\n -c \"ARROW#FFFFFF\" \\\n -u 1.1 -l 0 -v \"Upload\" -w 1100 -h 250 -t \"Upload Speed - `\/bin\/date +%A\", \"%d\" \"%B\" \"%Y`\" \\\n DEF:upload=$TRAF\/upload.rrd:upload:AVERAGE \\\n AREA:upload\\#FFFF00:\"Upload speed (Mbit\/s)\" \\\n GPRINT:upload:MIN:\"Min\\: %3.2lf \" \\\n GPRINT:upload:MAX:\"Max\\: %3.2lf\" \\\n GPRINT:upload:LAST:\"Current\\: %3.2lf\\j\" \\\n COMMENT:\"\\\\n\"\n \/usr\/bin\/rrdtool graph $TRAF\/download.png \\\n --start \"-3day\" \\\n -c \"BACK#000000\" \\\n -c \"SHADEA#000000\" \\\n -c \"SHADEB#000000\" \\\n -c \"FONT#DDDDDD\" \\\n -c \"CANVAS#202020\" \\\n -c \"GRID#666666\" \\\n -c \"MGRID#AAAAAA\" \\\n -c \"FRAME#202020\" \\\n -c \"ARROW#FFFFFF\" \\\n -u 1.1 -l 0 -v \"Download\" -w 1100 -h 250 -t \"Download Speed - `\/bin\/date +%A\", \"%d\" \"%B\" \"%Y`\" \\\n DEF:download=$TRAF\/download.rrd:download:AVERAGE \\\n AREA:download\\#00FF00:\"Download speed (Mbit\/s)\" \\\n GPRINT:download:MIN:\"Min\\: %3.2lf \" \\\n GPRINT:download:MAX:\"Max\\: %3.2lf\" \\\n GPRINT:download:LAST:\"Current\\: %3.2lf\\j\" \\\n COMMENT:\"\\\\n\"\n \/usr\/bin\/rrdtool graph $TRAF\/echoreply.png \\\n --start \"-3day\" \\\n -c \"BACK#000000\" \\\n -c \"SHADEA#000000\" \\\n -c \"SHADEB#000000\" \\\n -c \"FONT#DDDDDD\" \\\n -c \"CANVAS#202020\" \\\n -c \"GRID#666666\" \\\n -c \"MGRID#AAAAAA\" \\\n -c \"FRAME#202020\" \\\n -c \"ARROW#FFFFFF\" \\\n -u 1.1 -l 0 -v \"Ping\" -w 1100 -h 250 -t \"Ping Response - `\/bin\/date +%A\", \"%d\" \"%B\" \"%Y`\" \\\n DEF:echoreply=$TRAF\/echoreply.rrd:echoreply:AVERAGE \\\n AREA:echoreply\\#FF0000:\"Ping Response (ms)\" \\\n GPRINT:echoreply:MIN:\"Min\\: %3.2lf \" \\\n GPRINT:echoreply:MAX:\"Max\\: %3.2lf\" \\\n GPRINT:echoreply:LAST:\"Current\\: %3.2lf\\j\" \\\n COMMENT:\"\\\\n\"\n ;;\n (*)\n echo \"Invalid option.\";;\n esacLet\u2019s do some \u2018splaining\nSo firstly, copy everything, save it in a file (I called mine speedtest_rrd.sh), and chmod appropriately.\nLet me make an assumption that all your binary or executable files are in ~\/bin.\nchmod 755 ~\/bin\/speedtest_rrd.sh\nThe script can take one argument ( $1 ).\nArgument 1: (create)\nThis creates the rrd files to store history in, and creates some rrd info that we are going to display.\nArgument 2: (update)\nThis updates the rrd database with new values.\nArgument 3: (graph)\nThis draws the pretty graphs !\nYou may have noticed right at the very beginning of the script this line:\/usr\/local\/bin\/speedtest -s 5749 -p no > \/tmp\/speedtest.txt 2>\/dev\/null\nThis runs the speedtest cli, and saves the output into your \/tmp directory.\nRunning the script\nNow let\u2019s run it, and schedule it, then look at the results.\nRunning the script manually\nFirstly we need to create the rrd database:~\/bin\/speedtest_rrd.sh create\nresult:\nls -l \/var\/www\/html\/rrd\/*.rrd\n-rw-r--r-- 1 paul paul 35840 Sep 20 22:20 \/var\/www\/html\/rrd\/download.rrd\n-rw-r--r-- 1 paul paul 35840 Sep 20 22:20 \/var\/www\/html\/rrd\/echoreply.rrd\n-rw-r--r-- 1 paul paul 35840 Sep 20 22:20 \/var\/www\/html\/rrd\/upload.rrdsimple !\nNow let\u2019s do a test:~\/bin\/speedtest_rrd.sh update\nand now, let\u2019s create a graph:~\/bin\/speedtest_rrd.sh graph\nls -l \/var\/www\/html\/rrd\/\ntotal 188\n-rw-rw-r-- 1 paul paul 28167 Sep 20 22:20 download.png\n-rw-r--r-- 1 paul paul 35840 Sep 20 22:20 download.rrd\n-rw-rw-r-- 1 paul paul 27113 Sep 20 22:20 echoreply.png\n-rw-r--r-- 1 paul paul 35840 Sep 20 22:20 echoreply.rrd\n-rw-rw-r-- 1 paul paul 21572 Sep 20 22:20 upload.png\n-rw-r--r-- 1 paul paul 35840 Sep 20 22:20 upload.rrdAlright ! we have some data !\nScheduling the script\nOk, so now we have some data, let\u2019s start auto running the data collection.\nRemember me saying at the beginning you need unlimited data on your internet?\nLet me say that again .. YOU NEED UNLIMITED DATA ON YOUR INTERNET !!! \nThis script will thrash your internet usage!\nSo with that warning out of the way, let\u2019s chuck it in cron:\necho \"*\/5 * * * * paul \/home\/paul\/bin\/speedtest_rrd.sh update > \/dev\/null 2>&1 && \/home\/paul\/bin\/speedtest_rrd.sh graph > \/dev\/null 2>&1\" >> \/etc\/crontabnote: I am running this script as the user \u2018paul\u2019. Change to whatever user you are running this script as.\nThe result\nThat\u2019s it! we\u2019re running. Let that script chug away for a few days, and you\u2019ll get a result that looks like this:\nHappy speedtesting !\n Comments\n\t\tSteve\n November 04, 2020 at 06:55 AM\n This is really helpful, thank you! I made some minor edits to the script; I moved the actual speed test down to the update function so it wouldn\u2019t run a second time when creating the graphs.\n\t\tpaul\n November 04, 2020 at 09:03 PM\n Oh duh!! Good Spotting Steve!\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"28":{"url":"https:\/\/terminaladdict.com\/bash\/networking\/2020\/09\/24\/Awstats-static-reports-and-Nginx.html","title":"Awstats Static Reports And Nginx","content":" Awstats Static Reports And Nginx\n Posted on 24 Sep 2020 | Categories:\n bash,\n networking\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nSo, I run a few websites \ud83d\ude09 and most of those websites (including this one) I have Google Analytics installed.\nBut server logs can provide different information. So I\u2019m going to setup graphing and tracking my server access logs.\nSo my steps are going to be:\nInstall Awstats, along with some prerequisites for CPAN, and creating a password file.\n Install CPAN The Comprehensive Perl Archive Network, along with the GeoIP plugin.\n Write a bash script to create, update, and graph, some results (as well as a wee PHP script to make life easier).\n Profit!\nPrerequisites\nI\u2019m not going to talk you through setting up a Linux server, or Nginx, PHP-FPM (Fastcgi).\nI will assume that you have a running server.\nYour linux server can be any flavour you like, I prefer Debian and Ubuntu distros, and I prefer aptitude as a package manager; you can use whatever you like \ud83e\udd17.\nAssumptions\nI\u2019ll assume we store the Awstats DB in \/var\/lib\/awstats.\n I\u2019ll assume we store the static reports in \/var\/cache\/awstats.\nInstalling the packages\nHere we go:sudo aptitude install awstats libgeoip-dev build-essential openssl\nInstalling the GeoIP plugin\nSo first we need to setup CPAN:\n$ sudo cpan\nLoading internal logger. Log::Log4perl recommended for better logging\ncpan shell -- CPAN exploration and modules installation (v2.28)\nEnter 'h' for help.\ncpan[1]> Now, while in the CPAN shell, let\u2019s install some stuff.\nFirstly, CPAN itself, and then the GeoIP plugin.cpan[1]> make installcpan[1]> install Bundle::CPAN\nThat\u2019ll get you up and running ready to install from cpan.\nNow let\u2019s install the GeoIP plugin:cpan[1]> install Geo::IP\nSetting up Nginx\nSo, a few prerequisites are needed for Nginx to behave properly.\nFirstly, make sure you have PHP running using fastcgi (I\u2019m not showing you how to do this in this doc).\nNext, let\u2019s make sure logging is separate for each website:\nIn my server { block I have the following lines for logging:\nserver_name terminaladdict.com;\naccess_log \/var\/log\/nginx\/terminaladdict.com-access.log;\nerror_log \/var\/log\/nginx\/terminaladdict.com-error.log;I\u2019m going to add some config to my server block specifically for awstats:\nlocation ^~ \/awstats {\n\talias \/var\/cache\/awstats\/terminaladdict.com;\n\tlocation ~ \\.php$ {\n\t\tfastcgi_split_path_info ^(.+\\.php)(\/.+)$;\n\t\tfastcgi_pass unix:\/var\/run\/php\/php7.3-fpm.sock;\n\t\tfastcgi_param SCRIPT_FILENAME $request_filename;\n\t\tinclude fastcgi_params;\n\t}\n\tauth_basic \"Website Statistics\";\n\tauth_basic_user_file \/var\/lib\/awstats\/.htpasswd;\n}\nlocation ^~ \/awstats-icon {\n\talias \/usr\/share\/awstats\/icon\/;\n}Now reload nginx systemctl reload nginx.service\nPassword protect our stats\nLet\u2019s not go public with our stats \ud83d\ude06 \nIn the Nginx config above I provided for password protection, so let\u2019s create that .htpasswd file:\nprintf \"Hi_my_name_is:`openssl passwd -apr1`\\n\" >> \/var\/lib\/awstats\/.htpasswd\nPassword: *********\nVerifying - Password: *********Setting up Awstats\nRight, so for whatever reason, awstats installs a cron job that doesn\u2019t seem to work. \nSo let\u2019s turn it off:echo \"\" > \/etc\/cron.d\/awstats \nphew \ud83d\ude06\nNow let\u2019s create an awstats config for our website. \nAwstats expects the config to be named \u201cawstats.website.ext.conf\u201d.\nSomething like:\nawstats.terminaladdict.com.conf\n awstats.example.co.nz.conf\n awstats.subdomain.example.org.nz.conf\nI\u2019m creating a config for terminaladdict.com, so here we have it:\nLogFile=\"\/var\/log\/nginx\/terminaladdict.com-access.log\"\nSiteDomain=\"terminaladdict.com\"\nHostAliases=\"www.terminaladdict.com\"\nDirIcons=\"\/awstats-icon\"\nDirData=\"\/var\/lib\/awstats\"\nDNSLookup = 1\nLoadPlugin=\"geoip GEOIP_STANDARD \/usr\/share\/GeoIP\/GeoIP.dat\"\nHere\u2019s a warning !\nIf your website is super busy, probably disable DNSLookup, by setting it to 0\nDNSLooup = 1 will slow things down A LOT\nThe bash script\nWhile I was setting this up I read many articles about configuring nginx to using cgi-bin.php with fastcgi.\nFor me, it just didn\u2019t work, and I got bored trying to figure out why it didn\u2019t work!\nSo I wrote my own little bash script to update awstats db, generate static reports, and build an index.php for some of the directories, just for ease of use.\nHere is my script:\n#!\/bin\/bash\nAWSTATS=\/usr\/lib\/cgi-bin\/awstats.pl\nDIR=\/var\/cache\/awstats\nYEAR=`date +%Y`\nMONTH=`date +%m`\nPHPFILE=\"\n Awstats\n Stuff found in this directory\n\";\nfor c in `\/bin\/ls -1 \/etc\/awstats\/awstats.*.conf 2>\/dev\/null | \/bin\/sed 's\/^\\\/etc\\\/awstats\\\/awstats\\.\\(.*\\)\\.conf\/\\1\/'` `[ -f \/etc\/awstats\/awstats.conf ]`\ndo\n mkdir -p $DIR\/$c\/$YEAR\/$MONTH\/\n for d in $DIR $DIR\/$c $DIR\/$c\/$YEAR\n do\n echo \"$PHPFILE\" > $d\/index.php\n done\n $AWSTATS -config=$c -update\n # report for the year\n $AWSTATS -config=$c -output -month=all -staticlinks > $DIR\/$c\/$YEAR\/awstats.yearly.report.$c.html\n ln -sf $DIR\/$c\/$YEAR\/awstats.yearly.report.$c.html $DIR\/$c\/$YEAR\/1-start-here.html\n # report the for the current month\n $AWSTATS -config=$c -output -staticlinks > $DIR\/$c\/$YEAR\/$MONTH\/awstats.$c.html\n ln -sf $DIR\/$c\/$YEAR\/$MONTH\/awstats.$c.html $DIR\/$c\/$YEAR\/$MONTH\/index.html\n for stat in alldomains allhosts lasthosts unknownip alllogins lastlogins allrobots lastrobots urldetail urlentry urlexit browserdetail osdetail unknownbrowser unknownos refererse refererpages keyphrases keywords errors404 downloads\n do\n $AWSTATS -config=$c -output=$stat -month=all -staticlinks > $DIR\/$c\/$YEAR\/awstats.$c.$stat.html\n $AWSTATS -config=$c -output=$stat -staticlinks > $DIR\/$c\/$YEAR\/$MONTH\/awstats.$c.$stat.html\n done\ndoneWhat the script does is:\nSet up some vairable, including a variable named PHPFILE, that creates a PHP file for some directories.\n in a for loop, for each awstats.{websitename}.conf do\n make a directory if needed (mkdir -p)\n a new for loop, that creates a PHP file in the root directory, and the $YEAR directory\n Updates the stats $AWSTATS -config=$c -update\n create some soft links for ease of use\n a nested for loop that creates reports for the year, and the month\n 1). $AWSTATS -config=$c -output=$stat -month=all -staticlinks > $DIR\/$c\/$YEAR\/awstats.$c.$stat.html\n 2). $AWSTATS -config=$c -output=$stat -staticlinks > $DIR\/$c\/$YEAR\/$MONTH\/awstats.$c.$stat.html\n profit!\nAnd here is the result:\nThe PHP file that the script creates\n The Awstats Yearly report\n The Awstats Monthly report\nAutomating\nAnd of course, chuck it in cron so it updates regularly. \nI run mine at 17 minutes passed the hour, because - well I dunno - 17 seemed like a fun number to use \ud83e\udd2a. \nI stored the script in \/usr\/local\/bin and called it awstats.update_and_build.sh\n# awstats\n17 * * * * root \/usr\/local\/bin\/awstats.update_and_build.sh > \/dev\/null 2>&1Happy stats collecting !\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"29":{"url":"https:\/\/terminaladdict.com\/bash\/linux\/2020\/12\/02\/Animated-Christmas-Tree-Written-in-Bash.html","title":"Animated Christmas Tree Written In Bash","content":" Animated Christmas Tree Written In Bash\n Posted on 02 Dec 2020 | Categories:\n bash,\n linux\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nIt\u2019s Christmas OMG OMG OMG OMG \ud83c\udf84 \ud83c\udf85 \ud83e\udd36\nSo here is your TerminalAddict.com gift for 2020 \ud83c\udf81\ud83c\udf81\ud83c\udf81\nPrerequisites\nYou must have bash installed \ud83d\ude02\nAssumptions\nI\u2019ll assume we have bash installed \ud83d\ude1c\nThe code\ncat > ~\/xmas_tree.sh\n#!\/bin\/bash\n# tput is a command to manipulate the terminal, it can be used to change the color of text, apply effects, and generally brighten things up.\ntrap \"tput reset; tput cnorm; exit\" 2\nclear\ntput civis\nlin=2\ncol=$(($(tput cols) \/ 2))\nc=$((col-1))\nest=$((c-2))\ncolor=0\n# Set the text color to green to write the tree\ntput setaf 2; tput bold\n# Write the tree\nfor ((i=1; i"},"30":{"url":"https:\/\/terminaladdict.com\/jekyll\/development\/2021\/02\/03\/Jekyll-Categories-Based-Dynamic-Menu.html","title":"Jekyll Categories Based Dynamic Menu","content":" Jekyll Categories Based Dynamic Menu\n Posted on 03 Feb 2021 | Categories:\n jekyll,\n development\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nSo let\u2019s start by reminding every one on how to get started with Jekyll, in this post: Jekyll Getting Started\nThat should give a you a reminder of where to start off \ud83d\ude00\nNeeding a documentation repo\nA little while Atlassian announced that they are stopping support for local server installs of Confluence. Boring \u203c\ufe0f\nI have literally moved my content from Mediawiki to Confluence just two months ago \ud83d\ude2b\nI guess this has been on my mind for a while. I don\u2019t need a wiki, I need a documentation repository.\nSo a little bit of googling I find a nice simple template.\nThe template didn\u2019t use Bootstrap, or jQuery, which I thought would be fine \u2026 err .. I guess I\u2019m a Bootstrap \/ jQuery geek? LOL \ud83d\ude1d\nSo I do a litle bit of this, and little bit of that, and I have the basis of a docs website.\nSorting data\nMy first hurdle is I like categorising my data into \u201cspaces\u201d and then categories.\nWhat I really want is a structure like:\nPersonal\n - Animals\n - A cat named Tivo\n - Lexi the Spaniel\n - Technical-Docs\n - A script I wrote\n - A thing I learned\nNet Enterprises\n - Technical-Docs\n - Ip addresses\n - SMTP Server\n - General-Docs\n - Stuff\n - ThingsCreating a \u201ccollection\u201d\nso I\u2019ll start by creating a \u201ccollection\u201d in my _config.yml:\ncollections:\n docs:\n title: Documentation\n permalink: \/:path\/\n output: trueNow I\u2019ll need to create some rules for my documentation:\nA page title\n a \u201cspace\u201d\n a single category\n an order (because I\u2019m going to use that later on)\n---\ntitle: Lexi the Spaniel\nspace: Personal\ncategory: Animals\norder: 5\n---My documents are stored in the directory _docs\/Personal\/* and _docs\/Net-Enterprises\/*\ne.g. _docs\/Personal\/Lexi-The-Spaniel.md\nCreating a dynamic menu\nNow I need to create a menu.\nThis took me ages !!!! A couple of days of trying different things !!\nAnd the result \u2026 15 lines of code \ud83d\ude27\n {% assign space_groups = site.docs | group_by: 'space' %}\n {% for s_group in space_groups %}\n {{ s_group.name }}\n {% assign CATEGORIES = \"\" | split: ',' %}\n {% for s in s_group.items %}\n {% assign CATEGORIES = CATEGORIES | push: s.category | uniq %}\n {% endfor %}\n {% for cat in CATEGORIES %}\n {{ cat }}\n {% assign local_list = s_group.items | where: \"category\", cat %}\n {% for i in local_list %}\n {{ i.title }} - {{ site.baseurl }}{{ i.url }}\n {% endfor %}\n {% endfor %}\n {% endfor %}The Result\nLet skip straight to the screenshot \ud83d\ude02\nAnyway .. drop me a comment if you need help with Jekyll things\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"31":{"url":"https:\/\/terminaladdict.com\/jekyll\/development\/2021\/02\/04\/Markdown-Cheatsheet.html","title":"Markdown Cheatsheet","content":" Markdown Cheatsheet\n Posted on 04 Feb 2021 | Categories:\n jekyll,\n development\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nI use markdown a lot, but sometimes need a quick \u201ccheat sheet\u201d (because I\u2019m thinking about code, rather documenting normally)\nHere is my \u201ccheat sheet\u201d\nThis Markdown cheat sheet provides a quick overview of all the Markdown syntax elements. It can\u2019t cover every edge case, so if you need more information about any of these elements, refer to the reference guides for basic syntax and extended syntax.\nAlso note, all code highlight is done using Rouge\nBasic Syntax\nThese are the elements outlined in John Gruber\u2019s original design document. All Markdown applications support these elements.\nHeading\n# H1\n## H2\n### H3Bold\n**bold text**Italic\n*italicized text*Blockquote\n> blockquoteOrdered List\n1. First item\n2. Second item\n3. Third itemUnordered List\n- First item\n- Second item\n- Third itemCode\n`code`Horizontal Rule\n---Link\n[title](https:\/\/www.example.com)\n[title](https:\/\/www.example.com){: target=\"_blank\"}Image\n![alt text](image.jpg)Extended Syntax\nThese elements extend the basic syntax by adding additional features. Not all Markdown applications support these elements.\nTable\n| Syntax | Description |\n| ----------- | ----------- |\n| Header | Title |\n| Paragraph | Text |Fenced Code Block\n```\n{\n \"firstName\": \"John\",\n \"lastName\": \"Smith\",\n \"age\": 25\n}\n```Footnote\nHere's a sentence with a footnote. [^1]\n[^1]: This is the footnote.Heading ID\n### My Great Heading {#custom-id}Definition List\nterm\n: definitionStrikethrough\n~The world is flat.~~Task List\n- [x] Write the press release\n- [ ] Update the website\n- [ ] Contact the media\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"32":{"url":"https:\/\/terminaladdict.com\/jekyll\/development\/2021\/02\/05\/Jekyll-Backlinks.html","title":"Jekyll Backlinks","content":" Jekyll Backlinks\n Posted on 05 Feb 2021 | Categories:\n jekyll,\n development\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nI\u2019ve had a project going on for a month or so to re-do a Confluence wiki into Markdown files, hence why I pusblished The Markdown Cheatsheet, and Jekyll categories based menu.\nOne thing that can be handy in a wiki is \u201cback links\u201d i.e. what other pages link to this page.\nThe Requirements\nI want to automatically find, and display, all other pages in a Jekyll site that link to the existing page.\nRuby Plugin\nOk, so let\u2019s just skip straight to the meaty bit \ud83d\ude02\nIn your Jekyll root directory, if you don\u2019t already have a folder called _plugins then create one.\nmkdir _pluginsLet\u2019s create a file called _plugins\/backlinks_generator.rb\nclass BackLinksGenerator < Jekyll::Generator\n def generate(site)\n all_notes = site.collections['docs'].docs\n all_posts = site.posts.docs\n all_pages = site.pages\n all_docs = all_notes + all_posts + all_pages \n # Identify backlinks and add them to each doc\n all_docs.each do |current_note|\n notes_linking_to_current_note = all_docs.filter do |e|\n e.content.include?(current_note.url)\n end\n current_note.data['backlinks'] = notes_linking_to_current_note\n end\n end\nendHere\u2019s a brief run down of what the Ruby script does:\nCreates 3 arrays: all_notes (i.e. a collection), all_post, all_pages.\n Concatinates the 3 arrays into one larger array called all_docs.\n In the current page that Jekyll is processing, loop through the all_docs array and find out if there is a link to the current page.\n Store the found results in the page\/post.data as an array called backlinks ( i.e. page.backlinks or post.backlinks)\nSome CSS\nYeah, just so things look nice \ud83d\ude1d\n.backlink-box {\n background-color: #fffdf7;\n}\n.backlink-box:before {\n content: \"What links here\";\n font-style: italic;\n}\n.backlink-box li {\n line-height: 1em;\n}The Jekyll layout\nI learned quickly that everything seems to link to the home page (i.e. \u201c\/\u201d).\nSo while writing a section in my layout I had to include an exclusion (i.e. {% if page.url != home.url %} )\nNow each page has an array of backlinks, or doesn\u2019t.\nI\u2019ll check if backlinks exists, by checking if it is greater than 0 (zero), and if it is, I can just loop through it !\n{% assign home = site.html_pages | where: 'url', '\/' | first %}\n{% if page.url != home.url %}\n {% if page.showbacklinks == true %}\n {% if page.backlinks.size > 0 %}\n {% for backlink in page.backlinks %}\n {{ backlink.title }}\n {% endfor %}\n {% endif %}\n {% endif %}\n{% endif %}\n Note:\nYou can disable showing the backlink on a per page \/ per post basis by using the front matter\n\u2014\nshowbacklinks: no\n\u2014\nThe Result\nsweet screenshot goodness \u2026.\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"33":{"url":"https:\/\/terminaladdict.com\/development\/2021\/05\/12\/Making-a-Service-Worker-refresh-properly.html","title":"Making a Service Worker refresh properly","content":" Making a Service Worker refresh properly\n Posted on 12 May 2021 | Categories:\n development\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\nI\u2019ve been playing around in web development for years, in fact, the first web \u201capplication\u201d I wrote was in 1994, the year the world wide web was available to the general public in New Zealand.\nThe last couple of years I\u2019ve been focused on Progressive Web Apps (PWA\u2019s), and this includes using service workers, which are notoriously bad at breaking the refresh button in browsers.\nMaybe another title for this post might be: How to Fix the Refresh Button When Using a Service Worker \ud83d\udd04\nThe Backstory\nSo, let\u2019s start with: I use Google Workbox.\nThey even have a Github Repository.\nAlso, I am a New Zealander (a kiwi \ud83e\udd5d), and I host all my websites and apps in New Zealand. In fact, I run my own hosting and internet company called Net Enterprises Ltd.\nAnother (I think it might be little known) fact, is New Zealand isn\u2019t connected very well with the rest of the world in terms of fibre connections. So, something in the UK that might be simple, like loading the workbox library from the CDN, turns out to be a slow experience here in New Zealand.\nThe punchline? I host a local copy of all the libraries I use: jQuery, Boostrap, Popper.js, Workbox, DataTables, etc \u2026\nI wanted an easy method to update my workbox library locally.\nFortunately, Google provide a \u201cworkbox-cli\u201d to do exactly this.\nYou need Node installed, and npm-check-updates for my little script to work:\n#!\/bin\/bash\nNPM=\/usr\/bin\/npm\nNCU=\/usr\/bin\/ncu\nCURDIR=$(pwd)\nif [ ! -f $NPM ]; then\n echo npm\/node not installed\n exit 1\nfi\nif [ ! -f $NCU ]; then\n echo npm-check-updates not installed\n echo install it with\n echo sudo npm i -g npm-check-updates\n exit 1\nfi\nif [ ! -f $CURDIR\/node_modules\/workbox-cli\/build\/bin.js ]; then\n echo installing workbox-cli\n $NPM install workbox-cli\nfi\necho updating node_modules\n$NCU -u\n$NPM update\necho updating workbox local files\n$CURDIR\/node_modules\/workbox-cli\/build\/bin.js copyLibraries local_workboxRunning this script will create a local copy of the workbox library in a folder called \u201clocal_workbox\u201d.\nThe Service Worker\nSo, a key concept for a service worker is that, to load a service worker you need to run javascript in your page, then you have separate javascript running as the service worker.\nSo, let\u2019s get to it.\nThe Service Worker Lifecycle\nGoogle produces some great documentation entitled The Service Workers Lifecycle, but if you\u2019re starting out, this doc can be overwhelming.\nSo I\u2019m going to try and break this down as simply as I can (this is how I understood service workers).\nOn the first visit to a PWA a service worker is installed, and some cache maybe?\n The second visit to PWA the content is probably loaded from the cache.\n The PWA has some new content.\n On the third visit to the PWA (after the new content has been added), the content is loaded from the cache!!\n Wait?!?!? What?!?!? Where\u2019s the new content?????\n During the third visit a new version of the service worker is installed and sits in a state called \u201cwaiting\u201d.\n With some magically voodoo magic the new service worker is installed, replacing the first service worker.\n On the fourth visit to the PWA the new content appears.\nSo, there was definitely some weird thing I was missing about caching and loading new service workers.\nThis week I figured it out.\nI need check to see if there is a service worker in \u201cwaiting\u201d and prompt the user. (I actually saw this in real life on Tinder, last year sometime \ud83d\ude02).\nSo back to the code:\nCode in your page\nconst promptStr = 'New version of this site is available, do you want to update? It may take two reloads.';\nfunction createUIPrompt(opts) {\n if (confirm(promptStr)) {\n opts.onAccept()\n }\n}\n\/\/ register a service worker for offline content\n\/\/ This code sample uses features introduced in Workbox v6.\nimport {Workbox, messageSW} from '..\/local_workbox\/workbox-v6.1.5\/workbox-window.prod.mjs';\nif ('serviceWorker' in navigator) {\n const wb = new Workbox('sw.js');\n let registration;\n const showSkipWaitingPrompt = (event) => {\n const prompt = createUIPrompt({\n onAccept: () => {\n \/\/ Assuming the user accepted the update, set up a listener\n \/\/ that will reload the page as soon as the previously waiting\n \/\/ service worker has taken control.\n wb.addEventListener('controlling', (event) => {\n window.location.reload();\n });\n wb.messageSW({ type: 'SKIP_WAITING', payload: 'SKIP_WAITING' });\n },\n onReject: () => {\n prompt.dismiss();\n }\n });\n };\n \/\/ Add an event listener to detect when the registered\n \/\/ service worker has installed but is waiting to activate.\n wb.addEventListener('waiting', showSkipWaitingPrompt);\n wb.register().then(function() {\n \/\/ console.log('CLIENT: service worker registration complete.');\n }, function () {\n console.log('CLIENT: service worker registration failure.');\n });\n} else {\n console.log('CLIENT: service worker is not supported.');\n}Let\u2019s work through this script, top to bottom to see what it does.\nFirst off, there\u2019s a little function that creates a JS prompt, and on clicking \u201cok\u201d will return onAccept.\nThen we head to the meat of the script!\nWe import a couple of libraries from the workbox local copy: Workbox, and messageSW (Later we\u2019re going to send a message to the service worker!).\nLet\u2019s first check if the browser supports service workers (if \u2018serviceWorker\u2019 in navigator).\nThe we\u2019ll fire up a new Workbox object.\nHere\u2019s the tricky bit .. SkipWaiting \u2026\nThis had me stumped for a while, mainly because I didn\u2019t really understand how service workers worked!\nBut reading through the lifecycle, kind of got me to a point where I understood just enough.\nWe create a function showSkipWaitingPrompt that does 2 things:\nSend a message to the service worker that is \u201cwaiting\u201d to skipwaiting, and just install itself.\n Reload the page.\nNow we add an event listener that \u201clistens\u201d for the \u201cwaiting\u201d message in the browser, and when it hears it, it runs the showSkipWaitingPrompt function.\nNext, we register the service worker.\nPlus, I chuck in a couple of console.log\u2019s for good measure (so I can keep an eye of what\u2019s going on).\nthat\u2019s it .. that is our javascript module!!!\n Note: it\u2019s a module!!!\nWhich brings me to a key point!!\nWhen loading this javascript you must load it as a module in your browser:\n My Main body content\nNotice that script tag that has type=\u201dmodule\u201d?\nThe Service Worker code\nNow, my understanding of service workers is probably just enough to get me in trouble, so I\u2019d love to hear people\u2019s feedback about this.\nSo, here goes \u2026\nimportScripts(\"..\/local_workbox\/workbox-v6.1.5\/workbox-sw.js\");\nworkbox.setConfig({\n debug: false,\n modulePathPrefix: \"..\/local_workbox\/workbox-v6.1.5\/\"\n});\nvar CACHE_NAME='my-cache';\nworkbox.precaching.precacheAndRoute([\n{url: '\/', revision: '1620607563' },\n{url: '\/404.html', revision: '1620607563' },\n{url: '\/contact.html', revision: '1620607563' },\n{url: '\/history.html', revision: '1620607563' },\n{url: '\/personal.html', revision: '1620607563' },\n{url: '\/projects.html', revision: '1620607563' },\n{url: '\/staff.html', revision: '1620607563' },\n{url: '\/sw.js', revision: '1620607563' },\n{url: '\/sitemap.xml', revision: '1620607563' },\n{url: '\/robots.txt', revision: '1620607563' }\n], {\n directoryIndex: null,\n});\n\/\/ cache images\nworkbox.routing.registerRoute(\n ({request}) => request.destination === 'image',\n new workbox.strategies.CacheFirst({\n cacheName: CACHE_NAME,\n plugins: [\n new workbox.expiration.ExpirationPlugin({\n maxEntries: 60,\n maxAgeSeconds: 10 * 24 * 60 * 60 \/\/ 10 Days\n }),\n new workbox.cacheableResponse.CacheableResponsePlugin({\n statuses: [0, 200]\n }),\n ],\n })\n);\n\/\/ cache styles\nworkbox.routing.registerRoute(\n ({request}) => request.destination === 'style',\n new workbox.strategies.CacheFirst({\n cacheName: CACHE_NAME,\n plugins: [\n new workbox.expiration.ExpirationPlugin({\n maxEntries: 60,\n maxAgeSeconds: 10 * 24 * 60 * 60 \/\/ 10 Days\n }),\n new workbox.cacheableResponse.CacheableResponsePlugin({\n statuses: [0, 200]\n }),\n ],\n })\n);\nvar urlsToCache = [\n '\/',\n '\/404.html',\n '\/contact.html',\n '\/history.html',\n '\/personal.html',\n '\/projects.html',\n '\/staff.html',\n '\/sw.js',\n '\/sitemap.xml',\n '\/robots.txt'\n];\nself.addEventListener('install', function(event) {\n \/\/ Perform install steps\n event.waitUntil(\n caches.open(CACHE_NAME)\n .then(function(cache) {\n console.log('Opened cache');\n return cache.addAll(urlsToCache);\n })\n );\n});\nself.addEventListener('fetch', function(event) {\n event.respondWith(\n caches.match(event.request)\n .then(function(response) {\n \/\/ Cache hit - return response\n console.log('Returned from cache');\n if (response) {\n return response;\n }\n return fetch(event.request).then(\n function(response) {\n \/\/ Check if we received a valid response\n if(!response || response.status !== 200 || response.type !== 'basic') {\n return response;\n }\n \/\/ IMPORTANT: Clone the response. A response is a stream\n \/\/ and because we want the browser to consume the response\n \/\/ as well as the cache consuming the response, we need\n \/\/ to clone it so we have two streams.\n var responseToCache = response.clone();\n caches.open(CACHE_NAME)\n .then(function(cache) {\n console.log('Storing in cache');\n cache.put(event.request, responseToCache);\n });\n return response;\n }\n );\n })\n );\n});\nself.addEventListener('message', (event) => {\n console.log('Message received');\n if (event.data && event.data.type === 'SKIP_WAITING') {\n return self.skipWaiting();\n }\n});This was mostly lifted straight from Google\u2019s Advanced Recipes.\nThe bit that I changed was how to handle sending the SkipWaiting message.\nFor some reason I couldn\u2019t get messageSkipWaiting() loaded. I think they have removed it, but haven\u2019t updated the documentation?\nAnyway, I didn\u2019t feel like picky to bits Google\u2019s code, so I changed it to messageSW().\nWhich required me to add a small listener to the service worker:\nself.addEventListener('message', (event) => {\n console.log('Message received');\n if (event.data && event.data.type === 'SKIP_WAITING') {\n return self.skipWaiting();\n }\n});Pretty simple: listen for a message of type \u2018SKIP_WAITING\u2019, with the content \u2018SKIP_WAITING\u2019, then execute skipWaiting(), i.e. install the new service worker.\nYou can also see how I configure routes to cache, and how I add the files into the cache.\nConclusion\nFirstly, you can see how I use this exact principle with this web site, and how I integrate it with Jekyll.\nTake a look at the TerminalAddict.com Github repository.\nNow when new data is found on this website, a prompt is offered to the user, instead of hoping the user might come back later to see the new content.\nGive me some feedback\nAs I mentioned, I\u2019d love to hear people\u2019s thoughts.\nService workers are very polarising in the web community, some hate them, some love them.\nAnd everyone that uses them, seem to use them differently.\nSo drop me a message if you\u2019ve got something to share.\n Leave a Comment\n\t\t\t\tLiked what you've read?\n\t\t\t\tLeave me a message, or\n\t\t\t\t\tDrop me an email\n\t\t\t\tIt only takes a second of your time, but it means the world to me.\n\t\t\t\tDon't comment on Facebook, comment here !\n\t\t\t\tI don't keep any of your information, I only ask for a name, and an email to stop spammers!Pretty please !! :)\n Your email address will not be published. Required fields are marked *\n You won't be notified of replies, so come back and visit again!\n (Markdown is supported)\n My name is\n My email is\n My website is\n Notify me of replies\n Submit Comment\n Your browser does not support JavaScript! You can't submit a comment.\n "},"101":{"url":"https:\/\/terminaladdict.com\/page\/2\/","title":"Linux and SysAdmin tips and tricks - page 2","content":" Install Golang On Debian Buster\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\n | 10 Sep 2019 | linux, bash, golang \n Golang, or just simply Go is an open source programming language that makes it easy to build simple, reliable, and efficient software.\nThis is way easier than you think !!\n ... read more \u00bb\n Linux Streaming Webcams\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\n | 11 Mar 2019 | linux \n In this little snippet \/ howto I\u2019m going to show how I got a regular Logitech webcam streaming over the internet.\n ... read more \u00bb\n Web Development And Validation\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\n | 25 Feb 2019 | development \n So I do a bit of web development, and of course have developed all 3 my own sites numerous times. I\u2019m currently using Jekyll for my own sites (TerminalAddict.com, Loudas.com, and Paulwillard.nz), you can read about it here: Jekyll Getting Started. \nI want to talk about validation.\n ... read more \u00bb\n Comments On Blogs Vs Social Media\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\n | 06 Nov 2018 | development \n So I\u2019ve run a blog for years, since 2006. Sometimes I blog about personal adventures, sometimes I share coding and sys admin things, sometimes I just talk rubbish. So this thing has been on my mind for a while Comments\n ... read more \u00bb\n Jekyll Getting Started\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\n | 17 Oct 2018 | linux, jekyll, bash, development \n So my web development has taken an interesting path, not that different to some others.\nI start back in 1907 doing hand coded html, then moved to hand coded php, then dreamweaver, then CMS.\nEventually making it to Wordpress then back to PHP, and now to Jekyll\n ... read more \u00bb\n Debian Netboot ( Tftpd )\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\n | 08 Oct 2018 | linux, bash, mikrotik \n I pretty frequently install debian. There is always some sort of development going on that needs me to fire up a new install.\nI wrote a script to update my Debian Netboot directory etc.\n ... read more \u00bb\n Mikrotik Backup Script\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\n | 07 Oct 2018 | linux, bash, mikrotik \n I use Mikrotik routers a lot! I work for a WISP and there are a lot of Mikrotik devices.\n ... read more \u00bb\n Git Server (with Nginx)\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\n | 06 Oct 2018 | linux, bash \n Firstly, getting a git server up and running is pretty easy.\nMake sure git is installed aptitude install git\nCreate a git user adduser git\nChange the git user\u2019s shell echo $(which git-shell) >> \/etc\/shells, and then chsh git -s $(which git-shell)\n ... read more \u00bb\n Debian Stretch Timemachine\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\n | 05 Oct 2018 | linux, bash, osx \n In 2018 I got a flashy new MacBook Pro. Using the macOS integrated backup solution Time Machine I wanted to build an open source Apple Time Capsule.\nApple Mac OSX doesn\u2019t allow you to use a network share as a backup location.\nThe steps described below are tested on Debian Stretch but might also work on other Debian based distributions like Ubuntu.\n ... read more \u00bb\n Monitoring An Apc Ups\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\n | 04 Oct 2018 | linux, bash \n I have an APC UPS which I like to monitor, and graph, this is the code I use to do so.\n ... read more \u00bb\n Previous\n 1\n 2\n 3\n 4\n of 4\n Next\n "},"102":{"url":"https:\/\/terminaladdict.com\/page\/3\/","title":"Linux and SysAdmin tips and tricks - page 3","content":" Nftables Bash Script\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\n | 03 Oct 2018 | linux, bash \n In 2018 I changed from running iptables to running nftables. This is my BASH script I use on my firewall.\n ... read more \u00bb\n Netonix Backup Script\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\n | 02 Oct 2018 | bash, linux \n Working for a WISP I entensively use Netonix switches. I was asked to code a backup script with parameters in BASH.\n ... read more \u00bb\n Pauls Personal Homepage\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\n | 01 Oct 2018 | php, css \n After Google Homepage closed down I wrote my own rss aggregator using php and cron.\n ... read more \u00bb\n Install a ram drive in Windows 7\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\n | 16 Apr 2013 | development \n or How to move the Firefox or Chrome cache to a RAM disk and speed up surfing by 20% or more\n ... read more \u00bb\n Google Plus one (+1) on WordPress Theme\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\n | 02 Jun 2011 | php \n Here\u2019s one for the web developers of the world. Google plus one went live today, so I chucked together a couple of simple functions, to include in your WordPress functions.php theme file.\n ... read more \u00bb\n more bandwidth? yes please Mr Pacific Fibre\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\n | 23 May 2011 | networking \n It seems the international community is starting to notice some things in the NZ internet space. This recent story on El reg & Nz boffins anchor new submarine cable\n ... read more \u00bb\n Pirates vs Librarians\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\n | 18 May 2011 | networking \n Yep it\u2019s the important issues I consider !!!\n ... read more \u00bb\n God bless fibre (ultrafast broadband)\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\n | 16 May 2011 | networking \n I\u2019ve long been a fan of fast internet. When I built my country home 8 years ago I paid an extra $5000 to get a huge pole installed, so I could get wireless delivered (17kms line of site). At the time this was pretty cutting edge stuff, and\u00a0expensive\u00a0!!! but everything in my house uses the internet; my TV (TiVo) my phones (voip) my cell phones (3 android phones in the house) plus my idle iPad.\n ... read more \u00bb\n Why my iPad sits idle, and doesn't get used\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\n | 12 May 2011 | osx \n Well it seems maybe the honeymoon is over?\n ... read more \u00bb\n The shortest straw (or URL?)\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\n | 11 May 2011 | linux \n So todays project was shorten my URLs :)\n ... read more \u00bb\n Previous\n 1\n 2\n 3\n 4\n of 4\n Next\n "},"103":{"url":"https:\/\/terminaladdict.com\/page\/4\/","title":"Linux and SysAdmin tips and tricks - page 4","content":" Why Safari? Why you do this?\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\n | 08 May 2011 | osx \n Or why Safari on my iPad thinks it best to undo all my work!\n ... read more \u00bb\n Flared Borders with CSS\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\n | 08 May 2011 | css \n I want a Pure CSS menu with nice rounded corners\n ... read more \u00bb\n TerminalAddict version 2 ( HTML5 & CSS3 )\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\n | 06 May 2011 | css \n is this HTML5 and CSS3 I see before me?\n ... read more \u00bb\n Disable the new admin bar in wordpress\n by \n Paul Willard\n Paul Willard\n Senior Network and Systems Manager\n | 24 Feb 2011 | php \n Yep a geeky thing .. today word press updated to version 3.1\n ... read more \u00bb\n Previous\n 1\n 2\n 3\n 4\n of 4\n "},"105":{"url":"https:\/\/terminaladdict.com\/assets\/ta_skeleton\/","title":"TA Skeleton","content":" Linux\n php\n Mikrotik\n bash\n development\n Mountain biking with Helen\n by Paul Willard | April 27, 2015 at 12:37 AM | General Life \n On April 26, 2015 Helen and I went to Rotorua for some mountain biking, followed by a soak in the stream at kerosene creek. This is the video. Music: \"Happy feet\" performed by Kermit the Frog. \"Life's a happy song\" performed by Kermit the Frog and Bret McKenzie... read more \u00bb\n Linux\n php\n Mikrotik\n bash\n development\n Mountain biking with Helen\n by Paul Willard | April 27, 2015 at 12:37 AM | General Life \n On April 26, 2015 Helen and I went to Rotorua for some mountain biking, followed by a soak in the stream at kerosene creek. This is the video. Music: \"Happy feet\" performed by Kermit the Frog. \"Life's a happy song\" performed by Kermit the Frog and Bret McKenzie... read more \u00bb\n Linux\n php\n Mikrotik\n bash\n development\n Mountain biking with Helen\n by Paul Willard | April 27, 2015 at 12:37 AM | General Life \n On April 26, 2015 Helen and I went to Rotorua for some mountain biking, followed by a soak in the stream at kerosene creek. This is the video. Music: \"Happy feet\" performed by Kermit the Frog. \"Life's a happy song\" performed by Kermit the Frog and Bret McKenzie... read more \u00bb\n Linux\n php\n Mikrotik\n bash\n development\n Mountain biking with Helen\n by Paul Willard | April 27, 2015 at 12:37 AM | General Life \n On April 26, 2015 Helen and I went to Rotorua for some mountain biking, followed by a soak in the stream at kerosene creek. This is the video. Music: \"Happy feet\" performed by Kermit the Frog. \"Life's a happy song\" performed by Kermit the Frog and Bret McKenzie... read more \u00bb\n "}}