Systems Librarianship

Author: C. Sean Burns
Date: 2023-01-03
GitHub: @cseanburns


This short book is a work in progress. A main, first draft should be completed by the end of April 2023.

I am writing this book as I teach a course on Systems Librarianship. The book and course's goals are to provide a technical introduction to the basics of systems librarianship using Linux.

The course and book goals include:

  1. how to use the Linux command line in order to become more efficient computer users and more comfortable with using computers in general;
  2. how to use cloud computing resources and create virtual machines;
  3. how to manage projects using Git and GitHub;
  4. how to create a LAMP server, websites, and create a bare bones OPAC;
  5. how to install and configure content management systems, and;
  6. how to install and configure an integrated library system.

About This Book

The Systems Librarianship course is a brand new course (2023). I created the course to help future and current librarians become proficient in the kind of technology used to manage and provide electronic resources.

Since I use this book for my Systems Librarianship course, which I hope to teach each spring semester, this book will be a live document. Each semester that I teach this course, I will update the content in order to address changes in the technology and to edit for clarity when I discover some aspect of the book causes confusion or does not provide enough information.

A small part of this book will draw from my course on Linux Systems Administration, which I teach in the fall semesters.

This book is not a comprehensive introduction to systems librarianship. For example, this book does not cover software coding nor managerial duties, like issuing requests for proposals for software products, or budgeting. It is designed as an entry level course in the technical aspects of systems librarianship, and it is meant to go hand-in-hand with other courses taught in our program. That includes my course on electronic resource management but also other courses that my colleagues teach.

The book will start off as a series of transcripts, and over time, my hope is to build it out to a full fledged textbook on systems librarianship. I am using mdBook to build this work.

The content in this book is open access and licensed under the GNU GPL v3.0. Feel free to fork it on GitHub and modify it for your own needs.

History of Unix and Linux

An outline of the history of Unix and Linux.

Location: Bell Labs, part of AT&T (New Jersey), late 1960s through early 1970s

  • Starts with an operating system called Multics.
  • Multics was a time sharing system
    • That is, more than one person could use it at once.
  • But Multics had issues and was slowly abandoned
  • Ken Thompson found an old PDP-7. Started to write UNIX.
    • The ed line editor was written.
    • Pronounced e.d. but generally sounded out.
  • This version of UNIX would later be referred to as Research Unix
  • Dennis Ritchie, the creator of the C programming language, joined Thompson's efforts.

Location: Berkeley, CA (University of California, Berkeley), early to mid 1970s

  • The code for UNIX was not 'free software' but low cost and easily shared.
  • Ken Thompson visited Berkeley and helped install Version 6 of UNIX
  • Bill Joy and others contributed heavily
    • Joy created the vi text editor, a descendant of the popular Vim editor, many other important programs, and was a co-founder of Sun Microsystems
  • This installation of UNIX would eventually become known as the Berkeley Software Distribution, or BSD.


  • Until its breakup in 1984, AT&T was not allowed to profit off patents that were not directly related to its telecommunications businesses.
  • This agreement with the US government helped protect the company from monopolistic charges, and as a result, they could not commercialize UNIX.
  • This changed after the breakup. System V UNIX became the standard bearer of commercial UNIX.

Location: Boston, MA (MIT), early 1980s through early 1990s

  • In the late 1970s, Richard Stallman noticed that software began to become commercialized.
    • As a result, hardware vendors stopped sharing the code they developed to make their hardware work.
  • Software code became eligible for copyright protection with the Copyright Act of 1976
  • Stallman, who thrived in a hacker culture, began to battle against this turn of events.
  • Stallman created the GNU project, the free software philosophy, GNU Emacs, a popular and important text editor, and he wrote many other programs.
  • The GNU project is an attempt to create a completely free software operating system, that was Unix-like, called GNU.
  • By the early 1990s, Stallman and others had developed all the utilities needed to have a full operating system, except for a kernel, which they called GNU Hurd.
  • This included the Bash shell, written by Brian Fox.
  • The GNU philosophy includes several propositions that define free software:

The four freedoms, per GNU Project: 0. The freedom to run the program as you wish, for any purpose (freedom 0).

  1. The freedom to study how the program works, and change it so it does your computing as you wish (freedom 1). Access to the source code is a precondition for this.
  2. The freedom to redistribute copies so you can help others (freedom 2).
  3. The freedom to distribute copies of your modified versions to others (freedom 3). By doing this you can give the whole community a chance to benefit from your changes. Access to the source code is a precondition for this.

The Four Freedoms

The Unix wars and the lawsuit, late 1980s through the early 1990s

  • AT&T, after its breakup, began to commercialize Unix, and differences in AT&T Unix and BSD Unix arose.
  • The former was aimed at commercialization, and the latter aimed at researchers and academics.
  • UNIX Systems Laboratories, Inc. (USL, part of AT&T) sued Berkeley Software Design, Inc. (BSDi, part of the University of California, Berkeley) for copyright and trademark violations.
  • USL ultimately lost the case, but the lawsuit delayed adoption of BSD Unix.

Linux, Linus Torvalds, University of Helsinki, Finland, early 1990s

  • On August 25, 1991, Linus Torvalds announced that he had started working on a free operating system kernel for the 386 CPU architecture and for his specific hardware.
  • This kernel would later be named Linux.
  • Linux technically refers only to the kernel.
    • An operating system kernel handles startup, devices, memory, resources, etc.
    • A kernel does not provide user land utilities---the kinds of software they people use when using computers.
  • Torvalds' motivation was to learn about OS development but also to have access to a Unix-like system.
    • He already had access to an Unix-like system called MINIX, but MINIX had technical and copyright restrictions.
  • Torvalds has stated that if a BSD or if GNU Hurd operating system were available, then he may not have created the Linux kernel.
  • But Torvalds and others took the GNU utilities and created what is now called Linux or GNU/Linux.

Distributions, early 1990s through today

  • Soon after the Linux development, people would create their own Linux and GNU based operating systems and would distribute them.
  • As such, these Linux operating systems became referred to as distributions.
  • The two oldest distributions that are still in active development include:

Short History of BSD, 1970s through today

  • Unix version numbers 1-6 eventually led to BSD 1-4.
  • At BSD 4.3, all versions had some AT&T code.
    • Desire to remove this code led to BSD Net/1.
  • All AT&T code was removed by BSD Net/2.
  • BSD Net/2 was ported to the Intel 386 processor.
    • This became 386BSD and was made available in 1992, a year after the Linux kernel was released.
  • 386BSD split into two projects:
  • NetBSD split into another project: OpenBSD.
  • All three of these BSDs are still in active development.
  • From a bird's eye point of view, they each have different focuses:
    • NetBSD focuses on portability (MacOS, NASA)
    • FreeBSD focuses on wide applicability (WhatsApp, Netflix, PlayStation 4, MacOS)
    • OpenBSD focuses on security (has contributed a number of very important applications)

MacOS is based on Darwin, is technically UNIX, and is partly based on FreeBSD with some code coming from the other BSDs. See Why is macOS often referred to as 'Darwin'? for a short history.

Short History of GNU, 1980s through today

  • The GNU Hurd is still under active development, but it's the pre-production state.
  • The last release was 0.9 on December 2016.
  • A complete OS based on the GNU Hurd can be downloaded and ran. For example: Debian GNU/Hurd

Free and Open Source Licenses

In the free software and open source landscape, there are several important free and/or open source licenses that are used. The two biggest software licenses are based on the software used by GNU/Linux and the software based on the BSDs. They each take very different approaches to free and/or open source software. The biggest difference is this:

  • Software based on software licensed under the GPL must also be licensed under the GPL. This is referred to as copyleft software, and the idea is to propagate free software.
  • Software based on software licensed under the BSD license may be closed source and primarily must only attribute the original source code and author.

Draft Revision

History of Unix and Linux

The history of modern computer operating systems is a fascinating tale of innovation, collaboration, and the struggle to balance commercial interests with the ideals of free and open-source software. The story of Unix, and by extension, Linux, begins in the late 1960s at Bell Telephone Labs, a research program that was part of AT&T in New Jersey, with an operating system called Multics. Multics was a time-sharing system that allowed multiple users to access it simultaneously.

Ken Thompson, a computer programmer at Bell Labs, had been working on Multics when AT&T decided to withdraw from the project. He found an old PDP-7 and started to write a new operating system that would later be named UNIX. The initial version of UNIX was created with the help of the ed line editor, pronounced "e.d." but generally sounded out. Thompson was later joined in his efforts by Dennis Ritchie, the creator of the C programming language. This version of UNIX became known as Research Unix.

UNIX gained popularity and was eventually installed at the University of California, Berkeley, in the early to mid-1970s. The code for UNIX was not "free software" but was low-cost and easily shared. Bill Joy and others contributed heavily, and Joy created the vi text editor, a descendant of the popular Vim editor, as well as many other important programs. This installation of UNIX would eventually become known as the Berkeley Software Distribution, or BSD.

Until its breakup in 1984, AT&T was not allowed to profit off patents that were not directly related to its telecommunications businesses. This agreement with the US government protected the company from monopolistic charges, and as a result, they could not commercialize UNIX. This changed after the breakup, and System V UNIX became the standard bearer of commercial UNIX.

In the early 1980s through the early 1990s, in Boston, MA, at MIT, Richard Stallman noticed that software began to become commercialized. As a result, hardware vendors stopped sharing the code they developed to make their hardware work. Software code became eligible for copyright protection with the Copyright Act of 1976, and Stallman began to battle against this turn of events. He created the GNU project, the free software philosophy, GNU Emacs, a popular and important text editor, and many other programs. The GNU project was an attempt to create a completely free software operating system, that was Unix-like, called GNU. By the early 1990s, Stallman and others had developed all the utilities needed to have a full operating system, except for a kernel, which they called GNU Hurd. This included the Bash shell, written by Brian Fox.

The GNU philosophy includes several propositions that define free software, including the four freedoms:

  1. The freedom to run the program as you wish, for any purpose (freedom 0).
  2. The freedom to study how the program works and change it so it does your computing as you wish (freedom 1). Access to the source code is a precondition for this.
  3. The freedom to redistribute copies so you can help others (freedom 2).
  4. The freedom to distribute copies of your modified versions to others (freedom 3). By doing this, you can give the whole community a chance to benefit from your changes. Access to the source code is a precondition for this.

In the late 1980s through the early 1990s, AT&T began to commercialize UNIX, and differences in AT&T UNIX and BSD UNIX arose. The former was aimed at commercialization, and the latter aimed at researchers and academics. UNIX Systems Laboratories, Inc. (USL, part of AT&T) sued Berkeley Software Design, Inc. (BSDi, part of the University of California, Berkeley) for copyright and trademark violations. USL ultimately lost the case, but the lawsuit delayed adoption of BSD Unix.

In the early 1990s, at the University of Helsinki, Finland, a young computer science student named Linus Torvalds announced that he had started working on a free operating system kernel for the 386 CPU architecture and for his specific hardware. This kernel would later be named Linux. Linux technically refers only to the kernel, which handles startup, devices, memory, resources, and other core functions of an operating system. However, a kernel does not provide user land utilities, which are the kinds of software people use when using computers.

Torvalds' motivation for creating Linux was to learn about operating system development and to have access to a Unix-like system. He already had access to a Unix-like system called MINIX, but MINIX had technical and copyright restrictions. Torvalds has stated that if a BSD or GNU Hurd operating system were available, he may not have created the Linux kernel. Nonetheless, Torvalds and others took the GNU utilities and created what is now called Linux or GNU/Linux.

Soon after the development of Linux, people began creating their own Linux and GNU-based operating systems and distributing them. As such, these Linux operating systems became referred to as distributions. The two oldest distributions that are still in active development include Slackware and Debian.

The history of the BSD operating system dates back to the 1970s, with Unix versions 1-6 eventually leading to BSD 1-4. At BSD 4.3, all versions had some AT&T code. The desire to remove this code led to BSD Net/1. All AT&T code was removed by BSD Net/2. BSD Net/2 was then ported to the Intel 386 processor, which became 386BSD and was made available in 1992, a year after the Linux kernel was released. 386BSD split into two projects: NetBSD and FreeBSD. NetBSD split into another project, OpenBSD. All three of these BSDs are still in active development, and each has a different focus. NetBSD focuses on portability, FreeBSD focuses on wide applicability, and OpenBSD focuses on security and has contributed a number of important applications.

In the free software and open-source landscape, there are several important free and/or open-source licenses that are used. The two biggest software licenses are based on the software used by GNU/Linux and the software based on the BSDs. They each take very different approaches to free and/or open-source software. The GNU General Public License (GPL) requires that software based on software licensed under the GPL must also be licensed under the GPL, which is referred to as copyleft software, and the idea is to propagate free software. On the other hand, the BSD License allows software based on software licensed under the BSD license to be closed source and primarily requires only attribution to the original source code and author.

What is Linux?

The Linux Kernel

Technically, Linux is a kernel, and a kernel is a part of an operating system that oversees CPU activity like multitasking, as well as networking, memory management, device management, file systems, and more. The kernel alone does not make an operating system. It needs user land applications and programs, the kind we use on a daily basis, to form a whole, as well as ways for these user land utilities to interact with the kernel.

Linux and GNU

The earliest versions of the Linux kernel were combined with tools, utilities, and programs from the GNU project to form a complete operating system, without necessarily a graphical user interface. This association continues to this day. Additional non-GNU, but free and open source programs under different licenses, have been added to form a more functional and user friendly system. However, since the Linux kernel needs user land applications to form an operating system, and since user land applications from GNU cannot work without a kernel, some argue that the operating system should be called GNU/Linux and not just Linux. This has not gained wide acceptance, though. Regardless, credit is due to both camps for their contribution, as well as many others who have made substantial contributions to the operating system.

Linux Uses

We are using Linux as a server in this course, which means we will use Linux to provide various services. Our first focus is to learn to use Linux itself, but by the end of the course, we will also learn how to provide web and database services. Linux can be used to provide other services that we won't cover in this course, such as:

  • file servers
  • mail servers
  • print servers
  • game servers
  • computing servers

Although it's a small overall percentage, many people use Linux as their main desktop/laptop operating system. I belong in this camp. Linux has been my main OS since the early 2000s. While our work on the Linux server means that we will almost entirely work on the command line, this does not mean that my Linux desktop environment is all command line. In fact, there are many graphical user environments, often called desktop environments, available to Linux users. Since I'm currently using the Ubuntu Desktop distribution, my default desktop environment is called Gnome. KDE is another popular desktop environment, but there are many other attractive and useful ones. And it's easy to install and switch between multiple ones on the same OS.

Linux has become quite a pervasive operating system. Linux powers the hundreds of the fastest supercomputers in the world. It, or other Unix-like operating systems, are the foundation of most web servers. The Linux kernel also forms the basis of the Android operating system and of Chrome OS. The only place where Linux does not dominate is in the desktop/laptop space.

What is Systems Administration?


What is systems administration or who is a systems administrator (or sysadmin)? Let's start off with some definitions provided by the National Institute of Standards and Technology:

An individual, group, or organization responsible for setting up and maintaining a system or specific system elements, implements approved secure baseline configurations, incorporates secure configuration settings for IT products, and conducts/assists with configuration monitoring activities as needed.


Individual or group responsible for overseeing the day-to-day operability of a computer system or network. This position normally carries special privileges including access to the protection state and software of a system.

See: Systems Administrator @NIST

Specialized Positions

In addition to the above definitions, which broadly define the role, there are a number of related or specialized positions. We'll touch on the first three in this course:

  • Web server administrator:
    • "web server administrators are system architects responsible for the overall design, implementation, and maintenance of Web servers. They may or may not be responsible for Web content, which is traditionally the responsibility of the Webmaster (Web Server Administrator" @NIST).
  • Database administrator:
    • like web admins, and to paraphrase above, database administrators are system architects responsible for the overall design, implementation, and maintenance of database management systems.
  • Network administrator:
    • "a person who manages a network within an organization. Responsibilities include network security, installing new applications, distributing software upgrades, monitoring daily activity, enforcing licensing agreements, developing a storage management program, and providing for routine backups" (Network Administrator @NIST).
  • Mail server administrator:

Depending on where a system administrator works, they may specialize in any of the above administrative areas, or if they work for a small organization, all of the above duties may be rolled into one position. Some of the positions have evolved quite a bit over the last couple of decades. For example, it wasn't too long ago when organizations would operate their own mail servers, but this has largely been outsourced to third-party providers, such as Google (via Gmail) and Microsoft (via Outlook). People are still needed to work with these third-party email providers, but the nature of the work is different than operating independent mail servers.


It's not always necessary to get certified as a systems administrator to get work as one, but there might be cases where it is necessary; for example, in government positions or in large corporations. It also might be the case that you can get work as an entry level systems administrator and then pursue certification with the support of your organization.

Some common starting certifications are:

Plus, Google offers, via Coursera, a beginners Google IT Support Professional Certificate that may be helpful.


Getting involved in associations and related organizations is a great way to learn and to connect with others in the field. Here are few ways to connect.

LOPSA, or The League of Professional System Administrators, is a non-profit association that seeks to advance the field and membership is free for students.

ACM, or the Association for Computing Machinery, has a number of relevant special interest groups (SIGs) that might be beneficial to systems administrators.

NPA, or the Network Professional Association, is an organization that "supports IT/Network professionals."

Codes of Ethics

Systems administrators manage computer systems that contain a lot of data about us and this raises privacy and competency issues, which is why some have created code of ethics statements. Both LOPSA and NPA have created such statements that are well worth reviewing and discussing.

Keeping Up

Technology changes fast. In fact, even though I teach this course about every year, I need to revise the course each time, sometimes substantially, to reflect changes that have developed over short periods of time. It's also your responsibility, as sysadmins, to keep up, too.

I therefore suggest that you continue your education by reading and practicing. For example, there are lots of books on systems administration. O'Reilly continually publishes on the topic. RedHat, the makers of the Red Hat Linux distribution, and sponsors of Fedora Linux and CentOS Linux, provides the Enable Sysadmin site, with new articles each day, authored by systems administrators, on the field., also supported by Red Hat, publishes articles on systems administration. Command Line Heroes is a fun and informative podcast on technology and sysadmin related topics. Linux Journal publishes great articles on Linux related topics.


In this section I provided definitions of systems administrators and also the related or more specialized positions, such as database administrator, network administrator, and others.

I provided links to various certifications you might pursue as a systems administrator, and links to associations that might benefit you and your career.

Technology manages so much of our daily lives, and computer systems store lots of data about us. Since systems administrators manage these systems, they hold a great amount of responsibility to protect them and our data. Therefore, I provided links to two code of ethics statements that we will discuss.

It's also important to keep up with the technology, which changes fast. The work of a systems administrator is much different today than it was ten or twenty years ago, and that surely indicates that it could be much different in another ten to twenty years. If we don't keep up, we won't be of much use to the people we serve.

What is Systems Librarianship


Of course, let's begin with the question, what is systems librarianship? Normally we might go to the literature to answer a question like this. Indeed, the literature is helpful, but it's sparse. The LISTA database only returns 131 results with a 45 year coverage for a search using the thesauri term SYSTEMS Librarians. I can get more results if I expand the search query, but then I get less relevant results, and the main idea is the same: this is an understudied area of librarianship.

It's been that way for a while. Susan K. Martin wrote the following over 35 years ago:

Of the specialist positions that exist in libraries, none is as underexamined as those of the systems librarians---the people who identify the needs of the library for automated systems, cause these systems to be implemented, and analyze the operations of the library (p. 57).

Perhaps as a result of this underexamination, sometimes there is confusion around the requirements and skills needed in this area of librarianship. Martin (1988) captured this tension when she wrote the following in 1988, which is still true today:

Over the years the library world has argued whether systems librarians should be librarians who have learned information technologies, or computer experts who have learned about libraries (p. 61).

The argument is partly a matter of jurisdiction. Abbott (1998), writing on librarianship in the sociology of professions, illustrated how:

The future of librarianship thus hinges on what happens to the perpetually changing work of the profession in its three contexts: the context of larger social and culture forces, the context of other competing occupations, and the context of competing organizations and commodities. To these complex contextual forces, any profession responds with varying policies and internal changes (pp. 434-5).

Essentially, Abbott means that professions, like librarianship, are always changing. The mechanisms for that change are structural and cultural (Abbott, 2010), but a changing profession means that its "link of jurisdiction" (Abbott, 1998, p. 435) changes, too. It not only changes, but professions constantly compete with each other over to adopt new areas of jurisdiction. So when we ask, as Martin (1998) did, whether librarians should learn information technologies or whether computer experts should learn libraries, I find myself thinking the prior is more important for libraries and their patrons. It means that librarians are expanding their jurisdiction by also becoming computer experts rather than computer experts expanding theirs.

That leads us to the next questions: what does it mean to be a computer expert for a systems librarian? What does a systems librarians need to do and know?

The answer is that it is a mix. Some part of the work involves systems administration, but that has broad meanings, and systems librarianship is more specific. Or, it has a more specific domain: the domain of libraries and librarianship.

A systems librarian might thus be considered a library systems administrator. Under this view, they need to be someone who knows about libraries, how libraries work, what they do, about their patrons, what their values are, and then use that knowledge to build the infrastructure to support that.

Given this, and the technologies involved, such work requires constant learning. Jordan (2003) identified three areas of learning:

  • pre-service education in library schools
  • on the job training
  • professional development in the form of workshops, courses, and conferences (p. 273)

Pre-service, formal education is a small part of any professional's career, regardless if that profession is in medicine, law, or librarianship. Thus the goal of pre-service education is to prepare people to adapt and grow in their fields. Jordan (2003) wrote that:

While formal training is undoubtedly important, the ability to learn new technologies independently lies at the foundation of systems librarians' professional life, because they often have to use technologies, or make planning decisions about specific technologies, before they become common enough to be the subject of formal training sessions (p. 273).

Even though Jordan's article is 20 years old and the technology has changed a lot, the basic duties of the systems librarian remain the same (Fu, 2014; Gonzales, 2020). Wilson (1998), as cited in Jordan (2003), refers to a list of the "typical responsibilities of systems librarians." These responsibilities look different today, because the technology is different, but conceptually, they're the same as they were then. In fact, this work will focus on a subset of this list that includes:

  • integrated library system management
  • server management
  • documentation
  • technology exploration and evaluation (Jordan, 2003, p. 274)

Gonzales (2020) highlights these and more current areas that include:

  • content management systems
  • electronic resource management systems
  • website redesign
  • help and support

Other items on Jordan's (2003) list are still relevant, but due to various constraints, this work will not cover the following areas:

  • network design and management
  • desktop computing
  • application development
  • planning and budget
  • specification and purchasing
  • miscellaneous technology support
  • technical risk management (p. 274)

In short, this work specifically focuses on a few of the bigger technical aspects of systems librarianship. Other works (or courses) and other sources will provide learning opportunities on the more managerial and administrative functions of systems librarianship and librarianship, in general.

If you are interested in learning more about network design and administration, then I encourage you to read my chapters on Networking and TCP/IP and DNS and Domain Names in my book on Systems Administration with Linux.

If you are interested in learning about application development, then you can pursue courses in a variety of programming languages, such as R, Python, JavaScript, and PHP, as well as courses on relational databases, such as MySQL or PostgreSQL, and so forth.

As Jordan (2003) identified, there is a lack of formalized training in systems librarianship in LIS schools. This is as true today as it was in 2003. This course was created to address the lack of that training. However, it can only be a start. Technology is constantly changing, and that means we must always embrace more informal learning opportunities. LIS programs are only two or so years long (if attending full time), but our careers, hopefully, will span decades. So all this course can ever be is just a starting point.

It is a big start, though. This course should lay a strong foundation for self-growth and self-education in the variety of technologies that we will learn and use here. Although separate areas of librarianship, my work (and course) on electronic resource management complement this one in many ways. For example, this work supports several parts of the technology section in the NASIG Core Competencies for Electronic Resources Librarians. It is no coincidence these two areas of librarianship often overlap or are assumed in a single librarian position.

Cloud Computing

Lastly, I want to mention cloud computing. This has become a major area of change in the last decade or so. It used to be more common for librarians to install their integrated library system software and store their bibliographic data on their premises. In the last ten years, there has been more migration to the cloud, which means that both the integrated library system software and the bibliographic data are stored off-site. Liu & Cai (2013) highlight the beginning of this trend toward cloud computing that continues to play a large role in systems librarianship (Naveed et al., 2021). As Liu and Cai note:

Systems librarians used to make their livings by managing hosted library systems. This situation is silently changing with the library systems moving onto the cloud (p. 26).

This trend has changed some aspects of systems librarianship. It means that systems librarians, while still a technical area of librarianship, need to work more closely with the vendors who themselves are hosting library systems. However, the trend does not erase all locally hosted solutions. Many libraries and other information agencies continue to support local collections and will either host those locally or work to get the bibliographic information for those collections ingested into their cloud-based integrated library systems.


The remainder of the course will be more technical and will prepare you to work and understand the systems that support the modern library. We will cover a lot, too! We will begin with setting up virtual machine instances on Google Cloud. We will use a distribution of the Linux operating system for these virtual machines. We will then learn the basics of the Linux command line. Next, we will learn how to use the version control system called git. We will use git to document our work flows and push that documentation to On our Linux servers, we will create a web server out of what is called a LAMP stack, which stands for Linux, Apache, MySQL, and PHP. We will use the web server to setup a basic website and a bare bones OPAC. (I'll provide the code for this.) Then we will learn how to install and setup two content management systems: Wordpress and Omeka. Lastly, we will spend the final two weeks of the semester installing and setting up the open source Koha ILS.

Let's get started!


Abbott, A. (1998). Professionalism and the future of librarianship. Library Trends, 46(3), 430–443.

Abbott, A. (2010). Varieties of ignorance. The American Sociologist, 41(2), 174–189.

Gonzales, B. M. (2020). Systems librarianship: A practical guide for librarians. Rowman & Littlefield Publishers.

Fu, P. (2014). Supporting the next-generation ILS: The changing roles of systems librarians. Journal of Library Innovation, 5(1), 30–42.

Jordan, M. (2003). The self‐education of systems librarians. Library Hi Tech, 21(3), 273–279.

Liu, W., & Cai, H. (Heather). (2013). Embracing the shift to cloud computing: Knowledge and skills for systems librarians. OCLC Systems & Services: International Digital Library Perspectives, 29(1), 22–29.

Martin, S. K. (1988). The role of the systems librarian. Journal of Library Administration, 9(4), 57–68.

Naveed, M. A., Siddique, N., & Mahmood, K. (2021). Development and validation of core technology competencies for systems librarian. Digital Library Perspectives, 38(2), 189–204.

Ratledge, D., & Sproles, C. (2017). An analysis of the changing role of systems librarians. Library Hi Tech, 35(2), 303–311.

Wilson, T. C. (1998). Systems librarian: Desinging roles, defining skills. American Library Association.

Using Google Cloud (gcloud)

This section introduces us to Google Cloud (gcloud). We will use this platform to create virtual instances of the Ubuntu Server Linux operating system.

Using gcloud for Virtual Machines

Virtual Machines

Our goal in this section is to create a virtual machine (VM) instance. A VM is basically a virtualized operating system that runs on a host operating system. That host operating system may also be Linux, but it could be Windows or macOS. In short, when we use virtual machines, it means instead of installing an operating system (like Linux, macOS, Windows, etc) on a physical machine, we use virtual machine software to mimic the process. The virtual machine, thus, runs on top of our main OS. It's like an app, where the app is a fully functioning operating system.

In my Linux Systems Administration course, we used to use VirtualBox to create virtual machines with Linux as the virtual operating system. This worked despite whether you or I were running Windows, macOS, or Linux as our main operating systems. VirtualBox is freely available virtualization software, and using it let students and myself run Linux as a server on our own desktops and laptops without changing the underlying OS on those machines (e.g., Windows, macOS).

However, even though we virtualize an operating system when we run a VM, the underlying operating system and CPU architecture are still important. When Apple, Inc launched their new M1 (ARM-based) chip in 2020, it created problems for running non ARM-based operating systems as virtual machines (i.e., x86_64 chips).

Fortunately, we are able to solve that issue using a third-party virtualization platform. In this course, that means we're going to use gcloud (via Google). There are other options available that you can explore on your own.

Google Cloud / gcloud

Google Account

We need to have a personal Google account to get started with gcloud. I imagine most of you already have a Google account, but if not, go ahead and create one at

Google Cloud (gcloud) Project

Next, the gcloud software helps you us on a Google Cloud project on your own system. Once you've created that project, you can enable billing for that project, and then install the gcloud software on your local machine.

Follow Step 1 at the top of the Install the gcloud CLI page to create a new project. Also, review the page on creating and managing projects.

When you create your project, you can name it anything, but try to name it something to do with this course. E.g., I am using the name syslib-2023. Avoid using spaces when naming your project.

Then click on the Create button, and leave the organization field set to No Organization.

Google Billing

The second thing to do is to set up a billing account for your gcloud project. This does mean there is a cost associated with this product, but the good news is that our bills by the end of the semester should only amount to $5 to 10 dollars, at most. Follow Step 2 to enable billing for your new project. See also the page on how to create, modify, or close your self-serve Cloud Billing account

Install the latest gcloud CLI version

After you have set up billing, the next step is to install gcloud on your local machines. The Install the gcloud CLI page provides instructions for different operating systems.

There are installation instructions for macOS, Windows, Chromebooks, and various Linux distributions. Follow these instructions closely for the operating system that you're using. Note that for macOS, you have to choose among three different CPU/chip architectures. If you have an older macOS machine (before November 2020 or so), it's likely that you'll select macOS 64-bit (x86_64). If you have a newer macOS machine, then it's likely you'll have to select macOS 64-bit (arm64, Apple M1 silicon). It's unlikely that any of you are using a 32-bit macOS operating system. If you're not sure which macOS system you have, then let me know and I can help you determine the appropriate platform. Alternatively, follow these instructions to find your processor information:

  • click on the Apple menu
  • choose About This Mac
  • locate the Processor or Chip information

After you have downloaded the gcloud CLI for your particular OS and CPU architecture, you will need to open a command prompt/terminal on your machines to complete the instructions that describe how to install the gcloud CLI. macOS uses the Terminal app, which can located using Spotlight. Windows user can use Command.exe, which can be located by search also.

Windows users will download a regular .exe file, but macOS users will download a .tar.gz file. Since macOS is Unix, you can use the mv command to move that file to your $HOME directory. Then you extract it there using the tar command, and once extracted you can change to the directory that it creates with the cd command. For example, if you are downloading the X86_64 version of the gcloud CLI, then you would run the following commands:

For macOS users, this assumes the .tar.gz file was downloaded to your default Downloads folder:

cd ~/Downloads/
mv google-cloud-cli-392.0.0-darwin-x86_64.tar.gz ~/
cd ~/
tar -xzf google-cloud-cli-392.0.0-darwin-x86_64.tar.gz
cd google-cloud-sdk

Modify the above commands, as appropriate, if you're using the M1 or the M2 version of the gcloud CLI.

Initializing the gcloud CLI

Please follow the instructions from the Google Cloud documentation for your operating system.

Once you have downloaded and installed the gcloud CLI program, you need to initialize it on your local machine. Scroll down on the install page to the section titled Initializing the gcloud CLI. In your terminal/command prompt, run the initialization command, per the instructions at the above page:

gcloud init

And continue to follow the above instructions.

gcloud VM Instance

Once you've initialized gcloud, log into Google Cloud Console, which should take you to the Dashboard page.

Our first goal is to create a virtual machine (VM) instance. As a reminder, a VM is basically a virtualized operating system. That means instead of installing an operating system (like Linux, macOS, Windows, etc) on a physical machine, software is used to mimic the process.

gcloud offers a number of Linux-based operating systems to create VMs. We're going to use the Ubuntu operating system and specifically the Ubuntu 20.04 LTS version.

Ubuntu is a Linux distribution. There are many, many distributions of Linux, and most are probably listed on the DistroWatch site. A new version of Ubuntu is released every six months. The 20.04 signifies that this is the April 2020 version. LTS signifies Long Term Support. LTS versions are released every two years, and Canonical LTD, the owners of Ubuntu, provide standard support for LTS versions for five years.

LTS versions of Ubuntu are stable. Non-LTS versions of Ubuntu receive nine months of standard support, and generally apply cutting edge technology, which is not always desirable for server operating systems. Each version of Ubuntu has a code name. 20.04 has the code name Focal Fossa. You can see a list of versions, code names, release dates, and more on Ubuntu's Releases page.

We will create our VM using the gcloud console. To do so, follow these steps from the Project page:

  • Click on the hamburger icon (three vertical bars) in the top right corner.
  • Click on Compute Engine and then VM instances
  • Make sure your project is listed.
  • Next, click on Create Instance.
  • Provide a name for your instance.
    • E.g., I chose syslib-2023 (no spaces)
  • Under the Series drop down box, make sure E2 is selected.
  • Under the Machine type drop down box, select e2-micro (2 vCPU, 1 GB memory)
    • This is the lowest cost virtual machine and perfect for our needs.
  • Under Boot disk, click on the Change button.
  • In the window, select Ubuntu from the Operating system drop down box.
  • Select Ubuntu 20.04 LTS x86/64
  • Leave Boot disk type be set to Balanced persistent disk
  • Disk size should be set to 10 GB.
  • Click on the Select button.
  • Check the Allow HTTP Traffic button
  • Finally, click on the Create button to create your VM instance.

Later in the semester when we install Koha, we will need to create a virtual machine with more CPUs and memory. We will be charged more for those machines. Since we do not yet need the extra resources, we will start off with fairly low powered machines.

Connect to our VM

After the new VM machine has been created, we need to connect to it via the command line. macOS users will connect to it via their Windows users can connect to it via their command prompt.

We use a ssh command to connect to our VMs. The syntax follows this pattern:

gcloud compute ssh --zone "zone-info" "name-info" --project "project-id"

The values in the double quotes in the above command can be located in your Google Cloud console and in your VM instances section. See the course video for details.

Update our Ubuntu VM

The VM will include a recently updated version of Ubuntu 20.04, but it may not be completely updated. Thus the first thing we need to do is update our machines. On Ubuntu, we'll use the following two commands, which you should run also:

sudo apt update
sudo apt -y upgrade

Then type exit to logout and quit the connection to the remote server.


When you log into your machines, you'll note a command prompt that ends with a dollar sign $. This is where we type our commands. The command prompt also displays our location in the file system. The tilde ~ is a shorthand symbol for our home directory. By default, we are placed in our home directory whenever we login to our machines.


Lastly, we have installed a pristine version of Ubuntu, but it's likely that we will mess something up as we work on our systems. Or it could be that our systems may become compromised at some point. Therefore, we want to create a snapshot of our newly installed Ubuntu server. This will allow us to restore our server if something goes wrong later.

To get started:

  1. In the left hand navigation panel, click on Snapshots.

  2. At the top of the page, click on Create Snapshot.

  3. Provide a name for your snapshot: e.g., ubuntu-1.

  4. Provide a description of your snapshot: e.g.,

    This is a new install of Ubuntu 20.04.

  5. Choose your Source disk.

  6. Choose a Location to store your snapshot.

    • To avoid extra charges, choose Regional.
    • From the drop down box, select the same location (zone-info) your VM has
  7. Click on Create

Please monitor your billing for this to avoid costs that you do not want to incur.


Congratulations! You have just completed your first installation of a Linux server.

To summarize, in this section, you learned about and created a VM with gcloud. This is a lot! After this course is completed, you will be able to fire up a virtual machine on short notice and deploy websites and more.

Learning the Command Line

It's obviously more common for people today to learn how to use a computer via a graphical user interface (GUI), but there are benefits to learning a command line interface (CLI). In this section, we learn some of the basics of using the Bash shell as our CLI. Our primary goal is to learn how to use the CLI as a file manager and to perform some text editing. However, if you find this interface appealing, know that Bash is a full-fledged programming language, and I encourage you to explore it as a scripting language.

There are three reasons, from a systems administration point of view, to prefer the CLI over the GUI. First, the GUI entails extra software, and the more software we have on a server, the more resources (memory, CPU, storage, etc) that software consumes. We would much rather have our machine's resources being used to provide the services we build them to do than to run irrelevant software. Second, the extra software a GUI requires means that we expose our systems to additional security risks. That is, every time we install more software on our servers, the server becomes more vulnerable because all software has bugs. This means that we want to be conservative, careful, and protective of our systems. This is especially true for production systems. Third, graphical user interfaces do not provide a good platform for automation, at least not remotely as well as command line interfaces do. Working on the command line, becuase it is a text-based environment, in what is known as a shell, is a reproducible process. That is not as easily true in a GUI.

Fortunately, Linux, and many other Unix-like operating systems, have the ability to operate without graphical user interfaces. This is partly the reason why these operating systems have done so well in the server market.

In this section, our focus is learning the command line environment. We will do this using the Bash shell. We will learn how to use the shell, how to navigate around the filesystem, how to perform basic tasks, and explore other functions and utilities the shell has to offer.

Learn the Command Line Interface (CLI)


There are two major interfaces that we use to interact with our computers. The most common interface is the graphical user interface, or GUI. This interface largely emphasizes non-textual interaction, such as the mouse, fingers (touch screens), remote controls (e.g., smart TVs), and most recently, wearable tech such as VR headsets and like. All of the above mechanisms for interacting with our computer systems are worthwhile, but more importantly, they are all suited to specific ranges of engagement with our computers. That is, they afford certain kinds of actions (Dourish, 2001).

The other major way of interfacing with our computers is via the command line interface, or CLI. The CLI is also suited to specific ranges of engagement, and its the kind of engagement that often allows us greater control over our systems.

One reason the CLI provides greater control over our systems is because the interaction is all text-based. Text-based interaction requires more specificity than graphical-based interaction. By that I mean, it requires us to provide written instructions to a computer and to know what instructions to give it when we want the computer to perform some specific action. This means that we have to memorize some common instructions in order to use our systems. This is not necessarily difficult because many of the most common instructions, or commands, are mnemonic, but it does take some getting used to.

A second reason the CLI provides greater control over the system is that because it's text-based, it can be automated. We will not cover programming in this work or course, but know that all the commands that we will learn can be put in a text file, made into an executable file, and run like a program. This makes text-based interaction rather powerful.

Basic Commands

In light of that, I have developed two programs that will help you remember these basic commands. The commands that I'll ask you to learn encompass less than 0.3% of the commands that are available on a Linux system, but they are the most commonly used commands. Many of the other commands that are available are for very specific purposes. I'd estimate that despite having used the Linux command line for over 20 years, I've barely used 20% of them, and I might be stretching my estimate.

The first set of commands that I'll ask you to learn and practice include the following:

list files and directories.................. ls
print name of current/working directory..... pwd
create a new directory...................... mkdir
remove or delete an empty directory......... rmdir
change directory............................ cd
create an empty file........................ touch
print characters to output.................. echo
display contents of a text file............. cat
copy a file or directory.................... cp
move or rename a file or directory.......... mv
remove or delete a file or directory........ rm

You will practice these commands using the program that I wrote called learn-the-cli (I will show you how to install this and the other programs shortly).

I also developed a flashcards program that will help you learn an additional fifteen commands. This program is based on one created by someone else for a different purpose (see source code link above for credit). I'll explain these additional commands as we proceed through the semester. In the meantime, I'll ask that you periodically run the flashcards program to familiarize yourself with these commands, which includes the ones in the list above but also a few additional ones.

The Filesystem

In addition to the various commands that I'll ask you to learn, you will also have to learn the structure of the Linux filesystem. A filesystem has several meanings, but in this context, I refer to where the directories on the Linux system are placed. I find this to be the most difficult thing that new Linux users have to learn for a couple of reasons. First, modern operating systems tend to hide the filesystem from their users. So even though, for example, macOS is Unix, many macOS users that I have taught are completely unfamiliar with the layout of directories on their system. This is because, per my observations, macOS Finder does not show the filesytem by default these days. Instead it shows its users some common locations for folders. This might make macOS more usable to most users, but it makes learning the system more difficult.

What's common for both macOS and Linux operating systems is a filesytem based on a tree-like structure. These filesystems begin at what's called a root location. The root location is referenced by a forward slash: /. All directories branch off from root. The location to any directory is called a PATH. For example, our home directories on Linux will be located at the following PATH:


That PATH begins at root / and ends at home.

It is a little different for Windows users. Since Windows is not Unix-like, it uses a different filesystem hierarchy. Many Windows users might be familiar with the basics, such as the C: drive for the main storage device or the D: drive for an added USB stick. As such, the Windows operating system uses multiple root directories (C:, D:, E:, etc.) I encourage you to read the following article on A quick introduction to the Linux filesystem for Windows users. The article is published by Red Hat, which makes its own Linux distribution.

In short, learning the Linux filesystem requires adopting a new mental model about how the operating system organizes its directories and files. Like learning the basic commands, it's not too hard, but it may take time and practice before it sticks. To help learn it, I wrote an additional program that will let you practice navigating around the Linux filesystem and making some changes to it. The program is called learn-the-filesystem. Before you use this program, I would like to encourage you to read another Red Hat article on Navigating your filesystem in the Linux terminal. It includes sections that my program will cover that include:

  • viewing file lists
  • opening a folder (aka, a directory)
  • closing a folder
  • navigating directories
  • absolute paths

Bash: The Bourne Again Shell

I should point out that the command line interface that we are using on our Linux servers is provided by a shell. A shell is "both an interactive command language and a scripting language" (see link above). We will use the shell strictly as a command language, but if you're interested someday, I'd encourage you to explore Bash as a scripting language (I personally script in Bash quite a lot). There are a variety of shells available for Linux and other Unix-like operating systems, but the most popular one and the one we will be using is called Bash.

Bash is an acronym for the Bourne Again Shell because it's based on the original Unix shell called the Bourne shell, written by Stephen Bourne. Bash itself was written by Brian Fox.

I think it's important to know the history of the technologies that we use, and Bash has a super interesting history that pre-exists Linux. Therefore, I highly encourage you listen to the Command Line Heroes episode titled Heroes in a Bash Shell, narrated by Saron Yitbarek. The episode recounts Brian Fox's history with the Bash shell while he worked for the Free Software Foundation in the 1980s.


We will spend the next few weeks practicing these commands and learning the filesystem. We'll do this because knowing these things is integral to accomplishing everything else in this work, including installing and setting up our content management systems and the integrated library system.

In the video for this week, I'll show you how to install the three programs that I wrote or modified. We will use git to download them. The we will move the programs to a specific directory in our executable PATH. This will allow us to run them simply by typing their names.


To install my practice programs, login to your Linux virtual instances, and run the following commands. You will learn more about these commands shortly.

First, let's take a look at the contents of your home directory (the default directory you're in when you connect to your virtual machine):


Most likely, nothing will be listed.

Now let's retrieve the programs using the git command:

git clone

Run the ls command again, and you'll see a new directory called learn-the-commandline:


Next, copy the programs to an executable path:

sudo cp learn-the-commandline/* /usr/local/bin

Run the first program and work through it in order to learn some of the basic commands:


When ready, run the second program in order to learn about the Linux filesystem:


Finally, periodically run the flashcards program to refresh your memory of the basic commands, plus some other commands that you'll learn about soon:



Dourish, P. (2001). Where the Action Is: The Foundations of Embodied Interaction. MIT Press.

Text editors

As we learn more about how to work on the command line, we will acquire the need to write in plain text or edit configuration files. Most configuration files for Linux applications exist in the /etc directory, and are regular text files. For example, later in the semester we will install the Apache Web Server, and we will need to edit Apache's configuration files in the process.

In order to edit and save text files, we need a text editor. Programmers use text editors to write programs, but because programmers often work in graphical user environments, they may often use graphical text editors or graphical Integrated Development Environments (IDEs). It might be that if you work in systems librarianship, that you will often use a graphical text editor, but knowing something about how to use command line-based editors can be helpful.

What is a Plain Text?

Plain text is the most basic way to store human-readable textual information. Whenever we use a word processor program, like Microsoft Office, we are creating a complex series of files that instruct the Office application how to display the contents of the file as well as how the contents are formatted and arranged. This can easily be illustrated by using an archive manager to extract the contents of a .docx file. Upon examination, most of the files in a single .docx file are plain text that are marked up in XML. The files are packaged as a .docx file and then rendered by an application, commonly Microsoft Word, but any application that can read .docx files will do.

A plain text file only contains plain text. Its only arrangement is from top to bottom. It does not allow for any kind of additional formatting, and it does not include media. It is the closest thing the digital has to output produced by a typewriter, but a typewriter that's connected to the internet.

A lot of content is written in plain text. For example, HTML is written in plain text and the web browser uses the HTML markup to render how a page will look.

<p>This is using a HTML paragraph tag.
The web browser would normally render this like
the other paragraphs on this page.
However, it's written in a code block,
which allows us to display the HTML tags
and appear as if it's real source code.</p>

The rendered result is not plain text but HTML, just like the rendered result of all those XML files in a .docx file are not plain text but a .docx file. Softare is written in plain text files because programming languages cannot evaluate content that is not just text. Those of you who have learned how to use the R programming language wrote your R code in plain text likely using the RStudio IDE. For our purposes, we need plain text files to modify configuration files for the various programs that we will install later.

Why Edit in Plain Text

Most of the time when we configure software, we might do it, for example, by using our mouse to find the settings menu in some application that we are using. All that does, for the most part, is make changes to some text file somewhere. We will have to be more direct since we are working on the command line only. That is, the kind of settings configurations we will do will require editing a variety of plain text files that the programs will use to modify how they work. Often the settings for programs can only be modified by editing their plain text configuration files.

We will also soon be working with Git and GitHub. These will also require us to use plain text. More on that in a couple of chapters.


The nano text editor is one of the user-friendliest of the text editors available on the Linux command line, but it still requires some adjustment as a new command line user. The friendliest thing about nano is that it is modeless, which is what you're already accustomed to using. This means nano can be used to enter and manipulate text without changing to insert or command mode. It is also friendly because, like many graphical text editors and software, it uses control keys to perform its operations.

A modal text editor has modes such as insert mode or command mode. In insert mode, the user types text as anyone would in any kind of editor or word processor. The user switches to command mode to perform operations on the text, such as find and replace, saving, cutting and pasting but cannot insert text as they would in insert mode. Switching between modes usually involves pressing some specific keys. In Vim and ed(1), my text editors of choice, the user starts in command mode and switches to insert mode by pressing the letter i or the letter a. The user may switch back to command mode by pressing the Esc key in Vim or by pressing the period in a new line in ed(1).

The tricky part to learning nano is that the control keys are assigned to different keystroke combinations than what many graphical editors (or word processors) use by convention today. For example, instead of Ctrl-c or Cmd-c to copy text, in nano you press the M-6 key (press Alt, Cmd, or Esc key and 6) to copy. Then to paste, you press Ctrl-u instead of the more common Ctrl-v. Fortunately, nano lists the shortcuts at the bottom of the screen.

The shortcuts listed need some explanation, though. The carat mark is shorthand for the keyboard's Control (Ctrl) key. Therefore to Save As a file, we write out the file by pressing Ctrl-o (although Ctrl-s will work, too). The M- key is also important, and depending on your keyboard configuration, it may correspond to your Alt, Cmd, or Esc keys. To search for text, you press ^W, If your goal is to copy, then press M-6 to copy a line. Move to where you want to paste the text, and press Ctrl-u to paste.

We can start nano simply by typing nano on the command line. This will open a new, unsaved file with no content. Alternatively, we can start nano by specifying a file name after typing nano. For example, if I want to open a file called example.txt, then I type the following command:

nano example.txt

If the file doesn't exist, this will create it. If it does exit, then the above command will open it.

One of the other tricky things about nano is that the menu bar (really just a crib sheet, so to speak) is at the bottom of the screen instead of at the top, which is where we are mostly accustomed to finding it these days. Also, the nano program does not provide pop up dialog boxes. Instead, all messages from nano, like what to name a file when we save it, appear at the bottom of the screen.

Lastly, nano also uses distinct terminology for some of its functions. The most important function to remember is the Write Out function, which means to save.

For the purposes of this class, that's all you really need to know about nano. Use it and get comfortable writing in it. Some quick tips:

  1. nano file.txt will open and display the file named file.txt.
  2. nano by itself will open to an empty page.
  3. Save a file by pressing Ctrl-o.
  4. Quit and save by pressing Ctrl-x.
  5. Be sure to follow the prompts at the bottom of the screen.


In the prior lesson, we learned how to use the Bash interactive shell. We will continue to do that, but in the meantime, in this lesson, we begin to learn how to use a command line text editor, nano. We will use nano to edit configuration files and publish text to GitHub.

Searching with grep

We have available some powerful utilities and programs to process, manipulate, and analyze text files. In this section, we will focus on the grep utility, which offers some advanced methods for searching the contents of text files.


The grep command is one of my most often used commands. Basically, grep "prints lines that match patterns" (see man grep). In other words, it's search, and it's super powerful.

grep works line by line. So when we use it to search a file for a string of text, it will return the whole line that matches the string. This line by line idea is part of the history of Unix-like operating systems, and it's important to remember that most utilities and programs that we use on the commandline are line oriented.

"A string is any series of characters that are interpreted literally by a script. For example, 'hello world' and 'LKJH019283' are both examples of strings." -- Computer Hope. More generally, it's the literal characters that we type. It's data.

To visualize how grep works, let's consider a file called operating-systems.csv with content as seen below:

OS, License, Year
Chrome OS, Proprietary, 2009
FreeBSD, BSD, 1993
Linux, GPL, 1991
macOS, Proprietary, 2001
Windows NT, Proprietary, 1993
Android, Apache, 2008

We can use grep to search for anything in that file. Let's start with a search for the string Chrome. Notice that even though the string Chrome only appears once, and in one part of a line, grep returns the entire line.


grep "Chrome" operating-systems.csv


Chrome OS, Proprietary, 2009

Be aware that, by default, grep is case-sensitive, which means a search for the string chrome, with a lower case c, would return no results. Fortunately, grep has an -i option, which means to ignore the case of the search string. In the following examples, grep returns nothing in the first search since we do not capitalize the string chrome. However, adding the -i option results in success:


grep "chrome" operating-systems.csv




grep -i "chrome" operating-systems.csv


Chrome OS, Proprietary, 2009

We can also search for lines that do not match our string using the -v option. We can combine that with the -i option to ignore the string's case. Therefore, in the following example, all lines that do not contain the string chrome are returned:


grep -vi "chrome" operating-systems.csv


FreeBSD, BSD, 1993
Linux, GPL, 1991
iOS, Proprietary, 2007
macOS, Proprietary, 2001
Windows NT, Proprietary, 1993
Android, Apache, 2008

Sometimes data files, like spreadsheets, contain header columns in the first row. We can use grep to remove the first line of a file by inverting our search and select all lines not matching "OS" at the start of a line. Here the carat key ^ is a regex indicating the start of a line. Again, this grep command returns all lines that do not match the string os at the start of a line, ignoring case:


grep -vi "^os" operating-systems.csv


Chrome OS, Proprietary, 2009
FreeBSD, BSD, 1993
Linux, GPL, 1991
iOS, Proprietary, 2007
macOS, Proprietary, 2001
Windows NT, Proprietary, 1993
Android, Apache, 2008

Alternatively, since we know that the string Year comes at the end of the first line, we can use grep to invert search for that. Here the dollar sign key $ is a regex indicating the end of a line. Like the above, this grep command returns all lines that do not match the string year at the end of a line, ignoring case. The result, in this specific instance, is exactly the same as the last command:


grep -vi "year$" operating-systems.csv


Chrome OS, Proprietary, 2009
FreeBSD, BSD, 1993
Linux, GPL, 1991
iOS, Proprietary, 2007
macOS, Proprietary, 2001
Windows NT, Proprietary, 1993
Android, Apache, 2008

The man grep page lists other options, but a couple of other good ones include:

Get a count of the matching lines with the -c option:


grep -ic "proprietary" operating-systems.csv



Print only the match and not the whole line with the -o option:


grep -io "proprietary" operating-systems.csv



We can simulate a Boolean OR search, and print lines matching one or both strings using the -E option. We separate the strings with a vertical bar |. This is similar to a Boolean OR search since there's at least one match in the following string, there is at least one result.

Here is an example where only one string returns a true value:


grep -Ei "(bsd|atari)" operating-systems.csv


FreeBSD, BSD, 1993

Here's an example where both strings evaluate to true:


grep -Ei "(bsd|gpl)" operating-systems.csv


FreeBSD, BSD, 1993
Linux, GPL, 1991

By default, grep will return results where the string appears within a larger word, like OS in macOS.


grep -i "os" operating-systems.csv


OS, License, Year
Chrome OS, Proprietary, 2009
iOS, Proprietary, 2007
macOS, Proprietary, 2001

However, we might want to limit results so that we only return results where OS is a complete word. To do that, we can surround the string with special characters:


grep -i "\<os\>" operating-systems.csv


OS, License, Year
Chrome OS, Proprietary, 2009

Sometimes I find it hard to remember the backslash and angle bracket combinations because they're too much alike HTML syntax but not exactly like HTML syntax. Fortunately, grep has a -w option to match whole words:


grep -wi "os" operating-systems.csv


OS, License, Year
Chrome OS, Proprietary, 2009

Sometimes we want the context for a result; that is, we might want to print lines that surround our matches. For example, print the matching line plus the two lines after the matching line using the -A NUM option:


grep -i "linux" -A2 operating-systems.csv


Linux, GPL, 1991
macOS, Proprietary, 2001
Windows NT, Proprietary, 1993

Or, print the matching line plus the two lines before the matching line using the -B NUM option:


grep -i "linux" -B2 operating-systems.csv


Chrome OS, Proprietary, 2009
FreeBSD, BSD, 1993
Linux, GPL, 1991

We can combine many of the variations. Here I search for the whole word BSD, case insensitive, and print the line before and the line after the match:


grep -iw -C1 "bsd" operating-systems.csv


Chrome OS, Proprietary, 2009
FreeBSD, BSD, 1993
Linux, GPL, 1991

We can use another option to stop returning results after some number of hits. Here I use grep to return search for the string "proprietary" and stop after the first hit:


grep -i -m1 "proprietary" operating-systems.csv


Chrome OS, Proprietary, 2009

We can add the -n option to instruct grep to tell us what line number for each hit. Below we see that the string "proprietary" is found on lines 2, 5, and 6.


grep -in "proprietary" operating-systems.csv


2:Chrome OS, Proprietary, 2009
5:macOS, Proprietary, 2001
6:Windows NT, Proprietary, 1993

We can use grep to search for patterns in strings instead of literal words. Here we use what's called character classes and repetition to search for five letter words:


grep -Eiw "[a-z]{5}" operating-systems.csv


Linux, GPL, 1991
macOS, Proprietary, 2001

Or four letter numbers:


grep -Eiw "[0-9]{4}" operating-systems.csv


Chrome OS, Proprietary, 2009
FreeBSD, BSD, 1993
Linux, GPL, 1991
macOS, Proprietary, 2001
Windows NT, Proprietary, 1993
Android, Apache, 2008

grep can also search for words that begin with some letter and end with some letter and with a specified number of letters between. Here we search for words that start with m, end with s, and have three letters in the middle:


grep -Eiw "m.{3}s" operating-systems.csv


macOS, Proprietary, 2001


Here let's practice looking at the auth.log file. This file records all attempts to login to the system:

First, we change directory to /var/log.

Second, we use less to peruse the auth.log file.

Third, we do a simple grep search for the string invalid user and pipe that through another grep command that examines IP addresses.

Fourth, we do another simple search for a longer string and pipe that through other commands to sort the data.

cd /var/log
less auth.log
grep -E "session opened for user (sean|root)" auth.log | less
grep "invalid user" auth.log | grep -Eo "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" | sort | uniq -c | sort
grep "Connection closed by invalid user" auth.log | cut -d" " -f11 | sort | uniq -c | sort |less
grep "Connection closed by invalid user" auth.log | cut -d" " -f11 | sort | uniq -c | sort -r |less


grep is very powerful, and there are more options listed in its man page.

Note that I enclose my search strings in double quotes. For example: grep "search string" filename.txt It's not always required to enclose a search string in double quotes, but it's good practice because if your string contains more than one word or empty spaces, the search will fail.

The Linux (and other Unix-like OSes) command line offers a lot of utilities to examine data. It's fun to learn and practice these. Despite this, you do not have to become an advanced grep user. For most cases, simple grep searches work well.

If you want to learn more, there are many grep tutorials on the web.

Managing Software


Most Linux distributions use what's called a package manager to handle the installation, upgrades, and uninstalls of the software on a system. The Ubuntu distribution uses a package manager called dpkg and a front-end called apt (advanced package tool). We will use apt to install, update, and remove software from our servers.


In order to do the above tasks, we will need to use the sudo command. The sudo command allows us to "execute a command as another user" (see man sudo). If we have multiple users on a system, and if we have their passwords, then we could use sudo to run commands as if we were logged into their accounts.

However, the main use of sudo is to execute a command as the root user. The root user is the superuser account and as such, this user can perform administrative tasks that regular users cannot. For security purposes, regular accounts may not add, remove, or update software on a system, nor may they modify most files or directories outside their home directories. Using sudo allows regular users to perform maintenance tasks on our systems by executing commands as the root user. Some consider this safer than logging in as the root user.

Not all regular users can use the sudo command. On regular Ubuntu distributions, users must belong to the sudo group in order to run the sudo command. The groups command will return a list of groups that your account belongs to. On the Ubuntu version used by the Google Cloud Platform (GCP), the group of interest is called google-sudoers. The difference between the sudo group on regular Ubuntu distributions and the GCP version is that regular users in the google-sudoers group are not prompted for their password.

Down the line, we will need to use the sudo command to modify files, create directories, and perform other maintenance tasks needed to install and manage software. In this lesson, we will use sudo along with the apt commands to update our systems and install software.

sudo syntax

The sudo command is simple to use. When necessary, we use sudo by pre-pending it to the regular commands that we have already learned. In our home directories, for example, we don't need to use sudo to create a new directory with the mkdir command. Instead we just type mkdir data to create a new directory/folder called data. But outside our home directory, for example, in the directory /usr/local/bin. We need to use sudo to do such things. (This is why I used the sudo command when I showed you how to copy the Learn the Commandline programs to /usr/local/bin.) If I want to create a data directory in /usr/local/bin, then I have to use sudo at the beginning of my command:

cd /usr/local/bin
sudo mkdir data

Or, without changing to that directory, I can just specify the full path:

sudo mkdir /usr/local/bin/data

Or if I want to create a file in some other directory outside my home directory, then I have to use sudo there, too:

cd /etc
sudo touch data.csv

Or, without changing to that directory, I can specify the full path:

sudo touch /etc/data.csv


We will use sudo in the above ways soon enough, but for now, we will use sudo to install, update, and uninstall software on our systems.

Next I'll demonstrate the apt commands that we'll need.

sudo apt update

Your system keeps a record of what software is installed on your system and their version numbers. The sudo apt update command updates that list and compares the update to what's installed. That is, if you have a piece of software called acme1.1 on your system, and acme1.2 is available, then running sudo apt update will let you know that you can upgrade to acme1.2. It's good practice to run sudo apt update before installing or upgrading your system because this lets your system upgrade to the most recent version of what you want to install.

In short, this command is simply:

sudo apt update

sudo apt upgrade

Once your list of software has been updated, you can upgrade with the sudo apt upgrade command if there are any upgrades. When you run this command, and if there are any upgrades, you will be prompted to proceed. You can press Y to proceed, or N to cancel.

This command is simply:

sudo apt upgrade

If you want to install a piece of software, then you have to install it using its package name. Sometimes that means we have to search for the name of the package. This is one of the apt commands that does not require the use of sudo. sudo is not required because apt search does not modify the system. It simply helps you search for a package name.

For example, the man pages provide helpful documentation about how to use the commands on our systems, but the man pages can also be dense and not straightforward.

Fortunately, there's an application called tldr that is a community-driven application that provides simple help pages and examples of how to use some of the most commonly used commands.

To search for the tldr package, we execute the following command:

apt search tldr

This returns a list of results that match the search query. One of those results is the tldr package, which is simply named tldr. Not all packages are simply named, which is why we need to search for the specific name.

Note that sometimes when we search for a package, the list of results is quite long. In those cases, pipe the above command through the less pager to page through the results: apt search <packagename> | less

apt show

If we want more specific information about the package, we can use the apt show command along with the package name. Therefore, to get more information about the tldr application, we execute the following command:

apt show tldr

This will return a fuller description of the package (usually), as well as the URL to the application's website, plus other details. We do not need to use sudo here because we are not modifying the system. We are only retrieving information.

sudo apt install

To install the tldr application, we use the sudo apt install command along with the package name. We want to make sure that the name of the package is exactly what was returned from the apt search command. In the tldr case, it's pretty straightforward, and to install:

sudo apt install tldr

sudo apt remove

In order to remove a package, we use the sudo apt remove command. I like to add the --purge option because this also removes system configuration files that I probably do not need. That is, some applications install configuration files (configs). Configs are files that set application preferences in the /etc directory. Adding --purge will remove those configs.

To remove a package and its system configuration files (if any), we run the above command with the package name.

sudo apt --purge remove tldr

Some configs are stored in your home directory. Generally only end user applications install configs in our home directories. The --purge option will not remove those configs; instead, we have to remove them manually if we want.

sudo apt autoremove

One of the great things about dpkg and apt is that it installs and handles software dependencies really well. Dependencies are other software that software depends upon to run. That is, few computer applications are self-contained, and they often require other technology. When we uninstall (or remove) applications, the package manager does not auto uninstall those dependencies that were installed with it. We use the autoremove command to uninstall those:

sudo apt autoremove

sudo apt clean

When we install packages, some files are installed with them. The sudo apt clean removes those extra files and frees up disk space. It's a simple command:

sudo apt clean


The apt command makes it quite easy to manage software on our systems. We will use this command to install more complicated software later. Here's a list of commands we covered:

  • sudo apt update
  • sudo apt upgrade
  • apt search
  • apt show
  • sudo apt install
  • sudo apt --purge remove
  • sudo apt autoremove
  • sudo apt clean

Project Management with Git and GitHub

Every major software project requires management. This is because a lot of people are often involved in these projects and it takes some coordination for them to write the many thousands of lines of software code, which also requires management.

Git and GitHub are two of the most popular technologies used to manage such software projects. However, they can also be used for other purposes, such as for technical documentation. Providing good documentation is the key to being able to build on prior work, to make adjustments to our workflows, to recall the details of some process, and for students, it can help in retention and reflection. In the remainder of the semester, we will begin to install and configure some complicated pieces of software. In order to better understand what we will be doing, it will be helpful to document our processes.

Specifically, we will use Git and GitHub to begin to document and take notes as we install the Apache2 web server, the PHP scripting language, and the MySQL relational database. These three technologies, plus the Linux operating system, form what is called the LAMP stack. This stack forms the basis of most modern web applications.

I recently had the opportunity to sit down and interview ChatGPT, the artificial intelligent chat agent that has made headlines in recent weeks. I wanted to see how ChatGPT would respond to some questions about how Git and GitHub are used. I am, of course, being somewhat cheeky, but the reason that something like ChatGPT works at all is because it relies on data from across the web; that is, it relies on documentation.

I asked ChatGPT two, admittedly, leading questions. I think it's responses are on the mark.

Me: Why are Git and GitHub good tools for project management?

This was its response:

Git and GitHub are great tools for project management for several reasons:

Version control: Git is a distributed version control system that allows developers to track changes in the codebase over time. It provides a history of all changes made to the code, allowing developers to track down bugs and revert to previous versions of the code if needed. This makes it easy to collaborate with other developers, as everyone can work on the same codebase without interfering with each other's work.

Collaboration: GitHub is a web-based platform that allows multiple developers to work on the same project simultaneously. It provides tools for collaboration such as pull requests, code reviews, and issue tracking. This makes it easy for developers to collaborate and communicate with each other, share code, and make changes to the codebase.

Documentation: GitHub provides tools for documentation, including a wiki and a README file. These tools allow developers to document the project's features, installation instructions, and other details. This makes it easy for new developers to get up to speed with the project and for non-developers to understand the project's features and functionality.

Continuous Integration and Deployment: GitHub integrates with several continuous integration and deployment tools such as Travis CI, CircleCI, and Jenkins. These tools automate the build, test, and deployment process, ensuring that changes to the codebase are thoroughly tested before they are deployed to production.

Community: GitHub has a large community of developers who contribute to open source projects. Developers can use GitHub to showcase their work and collaborate with other developers on open source projects. This allows developers to learn from each other, build their portfolios, and contribute to the open source community.

Me: Then I asked a follow up question: "How might non-programmers use Git and GitHub?" This was its response:

Git and GitHub are primarily used by developers for version control and collaboration, but non-programmers can also use these tools for various purposes. Here are some examples:

Documentation: GitHub provides a platform for creating and sharing documentation. Non-programmers can use this platform to write and maintain documentation for their projects or organizations. For example, a technical writer can use GitHub to collaborate with developers and create technical documentation.

Project management: GitHub provides tools for issue tracking and project management. Non-programmers can use these tools to manage projects and track progress. For example, a project manager can create and assign tasks, track progress, and communicate with team members.

Content management: GitHub can be used as a content management system for non-programming projects. For example, a marketing team can use GitHub to manage content for their website or social media channels.

Collaboration: GitHub can be used as a collaboration platform for non-programming projects. For example, a team working on a research project can use GitHub to collaborate on data analysis and share findings.

Education: GitHub can be used in education for version control, collaboration, and project management. For example, a teacher can use GitHub to teach students how to collaborate on group projects, manage tasks, and share documents.

In summary, Git and GitHub can be used by non-programmers for various purposes, such as documentation, project management, content management, collaboration, and education.

Learn Git and GitHub


Git and GitHub are some of the most popular tools developers and others use to manage source code and documentation.

For the remainder of this course, we will use Git and GitHub to document what we learn as we proceed to install the following technologies:

  • the Apache2 web server
  • the PHP scripting language
  • the MySQL relational database
  • the WordPress content management system
  • the Omeka content management system
  • the Koha integrated library system


git is a "free and open source distributed version control system." While it is primarily used by software developers, researchers, and others to manage software code and documentation, it is also quite useful for other projects that are text-based. For example, this entire handbook is written in a text-editor, marked up in Markdown, managed using git, and publicly stored on a GitHub repository.


GitHub is a hosting site for projects and repositories managed using git. Other git-based hosting sites exist, such as GitLab, and it is also possible to create self-hosted repositories. GitHub and GitLab provide social features to enhance collaboration on projects. Each service has its own strengths, and these differences largely come into play with more advanced usage of git. The basics among them are the same, though.


Markdown is a simplified and highly versatile markup language. Text marked up with Markdown can be converted to other formats, including HTML, PDF, DOCX, ODT, EPUB, and more. The basic formatting options offered by Markdown include:

  • headings
  • bold
  • italic
  • blockquote
  • ordered lists
  • unordered lists
  • code
  • links
  • images
  • horizontal rule

More formatting options exist and are listed in a helpful cheatsheet.

When you write your documentation, you will mark it up with Markdown. It doesn't require a lot. The majority of the time, I only use the above elements (rarely do I use the images or the horizontal rule elements). Here is an example of a file marked up with Markdown:

# Title

## Subtitle

This is a paragraph. Just add an empty line between
paragraphs to create new paragraphs.

For example, this is the second paragraph. I'm following
this paragraph with an unordered list:

- I can write in **bold** or use *italics*.
- I can add a [link to someplace](
- I can add `code` in a sentence with backticks.
- Next I use a blockquote to **not** quote Benjamin
  Franklin, who it is often attributed to, but to probably
  quote Xun Kuang, a [fourth century Confucian

> Tell me and I forget. Teach me and I remember. Involve me
> and I learn. --Not Benjamin Franklin and probably Xun
> Kuang

And finally, a code block starts with three backticks on
their own line, followed by the code (or any kind of
pre-formatted text), followed by three closing backticks on
a their own line.

When you sync your documentation to your GitHub, your Markdown files will automatically be rendered into HTML. To facilitate it, name your files in a systematic way and use the .md file extension. For example, when we install the Apache2 web server, you can name it


We will be using these technologies for four primary reasons. First, these technologies see widespread usage in the technology sector, and this is true for library specific projects. For example, the software code for the Koha integrated library system is managed with git and stored on GitHub. So is Omeka. WordPress also has a presence on GitHub. Therefore I think it's important to acquire some hands-on experience with git and GitHub because it helps one become part of those communities, even if we have no intention to contribute code to these projects.

Second, we will soon install and configure these projects on our servers, and doing so involves complicated processes. Unlike the commands we have practiced so far, the installation and configuration of these technologies are not everyday tasks. This means that documenting how we install and configure them will help us reproduce the steps at later times. For example, I used to install, configure, and setup Omeka for one of our LIS courses, but I only had to do so once a year. There was no way that I would remember the installation process each year, but by keeping detailed notes, I was easily able to reproduce my steps from the prior year. This saved me tons of time.

Documentation can also serve to enhance our workflows. I was able to use my Omeka notes to create scripts to automate parts of the configuration process. For example, you can read through my scripts for setting up Omeka for LIS 602 on GitHub. Even if you don't code, documentation can still improve your workflows.

Third, the process of documenting a complex series of steps augments learning. It's a way to reflect on our tasks and to develop an eye for detail.

Lastly, I would know so much less than I do about Linux and about all these technologies if I hadn't had access to the documentation efforts that other people have contributed and added to the web. By sharing our notes on GitHub, we contribute back to that ecosystem.

How to Document

The first video for this week covers how I configured git on my Linux server, and how I started using GitHub. While I use git almost everyday, I don't often set up git on a new machine. Therefore, I wanted to show you a live view of the process and a live view of how I document as I work on a process. I hope that by showing you how I document the steps I took to set up git and GitHub, you will see how to adapt a documentation workflow for yourselves.

Setup Git and GitHub

In the process of setting up git and GitHub during the unscripted video, I created a GitHub repo for that documentation. You can see it at: Setup Git and GitHub. Click on the file to view the notes. Your task it to repeat the process.

Creating a LAMP Server

In this section, we learn how to set up a LAMP (Linux, Apache, MySQL, PHP) stack. This stack enables us to create a web server that provides extra funtionality via PHP and MySQL, both of which are required to run content management systems and integrated library systems.

Installing the Apache Web Server


Apache is an HTTP server, otherwise called web server software. Other HTTP server software exists. Another big one is nginx. At its most basic, an HTTP server essentially makes files available to others who are able to establish a connection to the computer and view the files with a web browser. Ergo, a web browser is, at its most basic, a file viewer.

It's important to understand the basics of an HTTP server, and therefore I ask you to read Apache's Getting Started page before proceeding with the rest of this section. Each of the main sections on that page describe the important elements that make up and serve a website, including

  • clients, servers, and URLs
  • hostnames and DNS
  • configuration files and directives
  • web site content
  • log files and troubleshooting


Before we install Apache, we need to update our systems first.

sudo apt update
sudo apt -y upgrade

Once the machine is updated, we can install Apache2 using apt. First we'll use apt search to identify the specific package name. I already know that a lot of results will be returned, so let's pipe the apt search command through head to look at the initial results:

sudo apt search apache2 | head

The package that we're interested in happens to be named apache2 on Ubuntu. This package name is not a given. On other distributions, like Fedora, the Apache package is called httpd. To learn more about the apache2 package, let's examine it with the apt show command:

apt show apache2

Once we've confirmed that apache2 is the package that we want, we install it with the apt install command. Press Y to agree to continue after running the command below:

sudo apt install apache2

Basic checks

One thing that makes Apache2, and some other web servers, powerful is the library of modules that extend Apache's functionality. We'll come back to modules soon. For now, we're going to make sure the server is up and running, configure some basic things, and then create a basic web site.

To start, let's use systemctl to acquire some info about apache2 and make sure it is enabled and running:

systemctl list-unit-files apache2.service
systemctl status apache2

The output shows that apache2 is enabled, which means that it will start running automatically when the computer gets rebooted.

The output of the second command also shows that apache2 is active, which means that it has started working.

Creating a web page

Since apache2 is up and running, let's look at the default web page.

There are two ways we can look at the default web page. We can use a command line web browser. There are a number available, but I like w3m.

We can also use our regular web browsers and view the site by entering the IP address of the server in our browser URL bar.

To check with w3m, we have to install it first:

sudo apt install w3m

Once it's installed, we can visit our default site using the loopback IP address (aka, localhost). From the command line on our server, we can run either of these two commands:

w3m localhost

We can also get the subnet/private IP address using the ip a command, and then use that with w3m. For example, if ip a showed that my NIC has an IP address of, then I could use w3m with that IP address:


If the apache2 installed and started correctly, then you should see the following text at the top of the screen:

Apache2 Ubuntu Default Page
It works!

To exit w3m, press q and then y to confirm exit.

To view the default web page using a regular web browser, like Firefox, Chrome, Safari, Edge, or etc., you need to get your server's public IP address. To do that, log into the Google Cloud Console. In the left hand navigation panel, hover your cursor over the Compute Engine link, and then click on VM instances. You should see your External IP address in the table on that page. You can copy that external IP address or simply click on it to open it in a new browser tab. Then you should see the graphical version of the Apache2 Ubuntu Default Page.

Note that most browsers nowadays may try to force HTTPS mode, and they also often hide the protocal from the URL. If your web page is not loading, make sure your URL is http://IP-ADDRESS and not https://IP-ADDRESS.

Please take a moment to read through the text on the default page. It provides important information about where Ubuntu stores configuration files and what those files do, and the document root, which is where website files are stored.

Create a Web Page

Let's create our first web page. The default page described above provides the location of the document root at /var/www/html. When we navigate to that location on the command line, we'll see that there is already an index.html file located in that directory. This is the Apache2 Ubuntu Default Page that we visited above in our browsers. Let's rename that index.html file, and create a new one:

cd /var/www/html/
sudo mv index.html index.html.original
sudo nano index.html

Note: we use sudo in this directory because we are working on files and directories outside our home directories. Thus, be careful here about the commands you run. Any mistake may result in deleting necessary files or directories.

If you know HTML, then feel free to write some basic HTML code to get started. Otherwise, you can re-type the content below in nano, and then save and exit out.

<title>My first web page using Apache2</title>


<p>Welcome to my web site.
I created this site using the Apache2 HTTP server.</p>


If you have your site open in your web browser, reload the page, and you should see the new text.

You can still view the original default page by specifying its name in the URL. Remember that web browsers are, at their most basic, simply file viewers. So it makes sense that you simply have to specify the name of the file you want to view. For example, if your external IP address is, then you'd specify it like so:


In this section, we learned about the Apache2 HTTP server. We learned how to install it on Ubuntu, how to use systemd (systemctl) commands to check its status, how to create a basic web page in /var/www/html, how to view that web page using the w3m command line browser and our regular graphical browser,

In the next section, we will install PHP, which will provide the language needed to connect to MySQL, and thus enable more data driven web sites.

Installing and Configuring PHP


Client-side programming languages, like JavaScript, are handled by the browser. Major browsers like Firefox, Chrome, Safari, Edge, etc. all include JavaScript engines that use just-in-time compilers to execute JavaScript code (Mozilla has a nice description of the process.) From an end user's perspective, you basically install JavaScript when you install a web browser.

PHP, on the other hand, is a server-side programming language, which means it must be installed on the server in order to be used. From a system or web administrator's perspective, this means that not only does PHP have be installed on a server, but it must also be configured to work with the HTTP server, which in our case is Apache2.

The main use of PHP is to interact with databases, like MySQL, MariaDB, PostgreSQL, etc., in order to create data-based page content. To begin to set this up, we have to:

  1. Install PHP and relevant Apache2 modules
  2. Configure PHP and relevant modules to work with Apache2
  3. Configure PHP and relevant modules to work with MySQL

Install PHP

As usual, we will use apt install to install PHP and relevant modules. Then we will restart Apache2 using the systemctl command. Use apt show [package_name] to read more about each package we will install. The first command below installs the php and the libapache2-mod-php packages. The latter package is used to create a connection between PHP and Apache2.

sudo apt install php libapache2-mod-php
sudo systemctl restart apache2

We can check its status and see if there are any errors:

systemctl status apache2

Check Install

To check that it's been installed and that it's working with Apache2, we can create a small PHP file in our web document root. To do that, we cd to the /var/www/html/ directory and create a file called info.php:

cd /var/www/html/
sudo nano info.php

In that file, add the following text, then save and close the file:


No visit that file using the external IP address for your server. For example, in Firefox, Chrome, etc, go to:


Again, be sure to replace the IP below with the IP address of your server and be sure to use http and not https.

You should see a page that provides system information about PHP, Apache2, and the server. The top of the page should look like Figure 1 below:

PHP install page
Fig. 1. A screenshot of the title of the PHP install page.

Basic Configurations

By default, when Apache2 serves a web page, it looks for and serves a file titled index.html, even if it does not display that file in the URL bar. Thus, actually resolves to in such cases.

However, if our plan is to provide for PHP, we want Apache2 to default to a file titled index.php instead of index.html file. To configure that, we need to edit the dir.conf file in the /etc/apache2/mods-enabled/ directory. In that file there is a line that starts with DirectoryIndex. The first file in that line is index.html, and then there are a series of other files that Apache2 will look for in the order listed. If any of those files exist in the document root, then Apache2 will serve those before proceeding to the next. We simply want to put index.php first and let index.html be second on that line. Before modifying this file, it's good practice to create a backup of the original. So we will use the cp command to create a copy with a new name, and then we will use nano to edit the file.

cd /etc/apache2/mods-enabled/
sudo cp dir.conf dir.conf.bak
sudo nano dir.conf

Next we change the line to this:

DirectoryIndex index.php index.html index.cgi index.xhtml index.htm

Whenever we make a configuration change, we can use the apachectl command to check our configuration:

apachectl configtest

If we get a Syntax Ok message, we can reload the Apache2 configuration and restart the service:

sudo systemctl reload apache2
sudo systemctl restart apache2

Create an index.php File

Now create a basic PHP page. cd back to the Apache2 document root directory and use nano to create and open an index.php file:

cd /var/www/html/
sudo nano index.php

Let's add some HTML and PHP to it. We will add PHP that functions as a simple browser detector. Add the following code:

<title>Broswer Detector</title>
<p>You are using the following browser to view this site:</p>

$user_agent = $_SERVER['HTTP_USER_AGENT'];

if(strpos($user_agent, 'Edge') !== FALSE) {
    $browser = 'Microsoft Edge';
} elseif(strpos($user_agent, 'Firefox') !== FALSE) {
    $browser = 'Mozilla Firefox';
} elseif(strpos($user_agent, 'Chrome') !== FALSE) {
    $browser = 'Google Chrome';
} elseif(strpos($user_agent, 'Opera Mini') !== FALSE) {
    $browser = "Opera Mini";
} elseif(strpos($user_agent, 'Opera') !== FALSE) {
    $browser = 'Opera';
} elseif(strpos($user_agent, 'Safari') !== FALSE) {
    $browser = 'Safari';
} else {
    $browser = 'Unknown';

if(strpos($user_agent, 'Windows') !== FALSE) {
    $os = 'Windows';
} elseif(strpos($user_agent, 'Linux') !== FALSE) {
    $os = 'Linux';
} elseif(strpos($user_agent, 'Mac') !== FALSE) {
    $os = 'Mac';
} elseif(strpos($user_agent, 'iOS') !== FALSE) {
    $os = 'iOS';
} elseif(strpos($user_agent, 'Android') !== FALSE) {
    $os = 'Android';
} else {
    $os = 'Unknown';

if($browser === 'Unknown' || $os === 'Unknown') {
    echo 'No browser detected.';
} else {
    echo 'Your browser is ' . $browser . ' and your operating system is ' . $os . '.';


Next, save the file and exit nano. In your browser, visit your external IP address site (again, replace your server's IP address):


Although your index.html file still exists in your document root, Apache2 now returns the index.php file instead. However, if for some reason the index.php was deleted, then Apache2 would revert to the index.html file since that's what is listed next in the dir.conf DirectoryIndex line.


In this section, we installed PHP and configured it work with Apache2. We also created a simple PHP test page that reported our browser user agent information on our website.

In the next section, we'll learn how to complete the LAMP stack by adding the MySQL relational database to our setup.

Installing and Configuring MySQL


We started our LAMP stack when we installed Apache2 on Linux, and then we added extra functionality when we installed and configured PHP to work with Apache2. In this section, our objective is to complete the LAMP stack and install and configure MySQL.

If you need a refresher on relational databases, see: Introduction to Relational Databases.

Install and Set Up MySQL

In this section, we'll learn how to install, setup, secure, and configure the MySQL relational database so that it works with the Apache2 web server and the PHP programming language.

First, let's install MySQL Community Server, and then log into the MySQL shell under the MySQL root account.

sudo apt install mysql-server

This should also start and enable the database server, but we can check if it's running and enabled using the systemctl command:

systemctl status mysql 

We can login to the database to test it. In order to do so, we have to become the root Linux user, which we can do with the following command:

sudo su

Note: we need to be careful when we enter commands on the command line, because it's a largely unforgiving computing environment. But we need to be especially careful when we are logged in as the Linux root user. This user can delete anything, including files that the system needs in order to boot and operate.

After we are Linux root, we can login to MySQL, run the show databases; command, and then exit with the \q command:

NOTE: we need to distinguish between the regular user prompt of our Linux accounts and the MySQL prompt below. In the following, I will use the greater than symbol > to represent the MySQL prompt. Do not type that prompt when you are using MySQL.

First, connect to the MySQL server as the MySQL root user:

mysql -u root

Then request a list of the databases:

show databases;

And the following databases should be returned:

| Database           |
| information_schema |
| mysql              |
| performance_schema |
3 rows in set (0.002 sec)

Note: If we are logging into the root database account as the root Linux user, we don't need to enter our password.

Create and Set Up a Regular User Account

We need to reserve the root MySQL user for special use cases and instead create a regular MySQL user, or more than one MySQL user, as needed.

To create a regular MySQL user, we use the create command. In the command below, I'll create a new user called opacuser with a complex password within the single quotes at the end (marked with a series of Xs here for demo purposes). From the MySQL prompt:

create user 'opacuser'@'localhost' identified by 'XXXXXXXXX';

If the prompt returns a Query OK message, then the new user should have been created without any issues.

Create a Practice Database

As the root database user, let's create a new database for a regular, new user.

The regular user will be granted all privileges on the new database, including all its tables. Other than granting all privileges, we could limit the user to specific privileges, including: CREATE, DROP, DELETE, INSERT, SELECT, UPDATE, and GRANT OPTION. Such privileges may be called operations or functions, and they allow MySQL users to use and modify the databases, where appropriate. For example, we may want to limit the opacuser user to only be able to use SELECT commands. It totally depends on the purpose of the database and our security risks.

From the MySQL query prompt, run the following commands to create a new database opacdb and to grant all privileges to opacdb to the MySQL user opacuser:

create database opacdb;
grant all privileges on opacdb.* to 'opacuser'@'localhost';
show databases;

Exit out of the MySQL database as the root MySQL user, and then exit out of the root Linux user account, and you should be back to your normal Linux user account:


And then exit out of the Linux root user account:


Note: relational database keywords are often written in all capital letters. As far as I know, this is simply a convention to make the code more readable. However, in most cases I'll write the keywords in lower case letters. This is simply because, by convention, I'm super lazy.

Logging in as Regular User and Creating Tables

We can now start doing MySQL work. As a reminder, we've created a new MySQL user named opacuser and a new database for opacuser that is called opacdb. When we run the show databases command as the opacuser user, we should see the opacdb database. Note below that I use the -p option. This instructs MySQL to request the password for the opacuser user, which is required to log in.

mysql -u opacuser -p

Then from the MySQL prompt, list the available databases and switch to the new opacdb database:

show databases;
use opacdb;

A database is not worth much without data. In the following code, I create and define a new table for our opacdb database. The table will be called books, and it will contain data describing some books. We will keep this table very simple and use only three fields:

create table books (
id int unsigned not null auto_increment,
author varchar(150) not null,
title varchar(150) not null,
copyright date not null,
primary key (id)

You can confirm that the table was created by running the following two commands, which lists the available tables and then describes the books table:

show tables;
describe books;

Congratulations! Now create some records for that table.

Adding records into the table

We can populate our opacdb database with some data. (I simply picked the first book listed from the NYTimes best lists of books for the years 2019-2022.) We'll use the insert command to add our records into our distribution table:

insert into books (author, title, copyright) values
('Jennifer Egan', 'The Candy House', '2022-04-05'),
('Imbolo Mbue', 'How Beautiful We Were', '2021-03-09'),
('Lydia Millet', 'A Children\'s Bible', '2020-05-12'),
('Julia Phillips', 'Disappearing Earth', '2019-05-14');

Now we can view all the records that we just created with the MySQL select command:

select * from books;

Success! Now let's test our table.

Testing Commands

We will complete the following tasks to refresh our MySQL knowledge:

  • retrieve some records or parts of records,
  • delete a record,
  • alter the table structure so that it will hold more data, and
  • add a record

Reminder: each MySQL command ends with a semi-colon. Some of the following MySQL commands are single-line, but others are multi-line. Regardless if a MySQL command is one-line or multi-line, it doesn't end until it ends with a semi-colon:

select author from books;
select copyright from books;
select author, title from books;
select author from books where author like '%millet%';
select title from books where author like '%mbue%';
select author, title from books where title not like '%e';
select * from books;
alter table books add publisher varchar(75) after title;
describe books;
update books set publisher='Simon \& Schuster' where id='1';
update books set publisher='Penguin Random House' where id='2';
update books set publisher='W. W. Norton \& Company' where id='3';
update books set publisher='Knopf' where id='4';
select * from books;
delete from books where author='Julia Phillips';
insert into books
(author, title, publisher, copyright) values
('Emma Donoghue', 'Room', 'Little, Brown \& Company', '2010-08-06'),
('Zadie Smith', 'White Teeth', 'Hamish Hamilton', '2000-01-27');
select * from books;
select author, publisher from books where copyright < '2011-01-01';
select author from books order by copyright;

Install PHP and MySQL Support

The next goal is to complete the connection between PHP and MySQL so that we can use both for our websites.

First install PHP support for MySQL. We're installing some modules alongside the basic support. These may or may not be needed, but I'm installing them to demonstrate some basics.

sudo apt install php-mysql php-mysqli

And then restart Apache2 and MySQL:

sudo systemctl restart apache2
sudo systemctl restart mysql

Create PHP Scripts

In order for PHP to connect to MySQL, it needs to authenticate itself. To do that, we will create a login.php file in /var/www/html. We also need to change the group ownership of the file and its permissions so that the file can be read by the Apache2 web server but not by the world, since this file will store password information.

cd /var/www/html/
sudo touch login.php
sudo chmod 640 login.php
sudo chown :www-data login.php
ls -l login.php
sudo nano login.php

In the file, add the following credentials. If you used a different database name than opacdb and a different username than opacuser, then you need to substitute your names below. You need to use your own password where I have the Xs:

<?php // login.php
$db_hostname = "localhost";
$db_database = "opacdb";
$db_username = "opacuser";
$db_password = "XXXXXXXXX";

Next we create a new PHP file for our website. This file will display HTML but will primarily be PHP interacting with our books database.

Create a file titled opac.php.

sudo nano opac.php

Then copy over the following text (I suggest you transcribe it, especially if you're interested in learning a bit of PHP, but you can simply copy and paste it into the nano buffer):

<title>MySQL Server Example</title>

<h1>A Basic OPAC</h1>

<p>We can retrieve all the data from our database and book table
using a couple of different queries.</p>


// Load MySQL credentials
require_once 'login.php';

// Establish connection
$conn = mysqli_connect($db_hostname, $db_username, $db_password) or
  die("Unable to connect");

// Open database
mysqli_select_db($conn, $db_database) or
  die("Could not open database '$db_database'");

echo "<h2>Query 1: Retrieving Publisher and Author Data</h2>";

// Query 1
$query1 = "select * from books";
$result1 = mysqli_query($conn, $query1);

while($row = $result1->fetch_assoc()) {
	echo "<p>Publisher " . $row["publisher"] .
		" published a book by " . $row["author"] .


echo "<h2>Query 2: Retrieving Author, Title, Date Published Data</h2>";

$result2 = mysqli_query($conn, $query1);
while($row = $result2->fetch_assoc()) {
	echo "<p>A book by " . $row["author"] .
		" titled <em>" . $row["title"] .
		"</em> was released on " . $row["copyright"] .

// Free result2 set

/* Close connection */



Save the file and exit out of nano.

Test Syntax

After you save the file and exit the text editor, we need to test the PHP syntax. If there are any errors in our PHP, these commands will show the line numbers that are causing errors or leading up to errors. Nothing will output if all is well with the first command. If all is well with the second command, HTML should be outputted:

sudo php -f login.php
sudo php -f index.php


Congratulations! If you've reached this far, you have successfully created a LAMP stack. In the process, you have learned how to install and set up MySQL, how to create MySQL root and regular user accounts, how to create a test database with play data for practicing, and how to connect this with PHP for display on a webpage.

In regular applications of these technologies, there's a lot more involved, but completing the above process is a great start to learning more.

Creating a Bare Bones OPAC

In this section, we're going to create a bare bones and very basic OPAC. The idea is simply to acquire an intuition and understanding of how data from a relational database is retrieved and entered using various technologies.

A real integrated library system is much more complex than what we are doing here, but the fundamental ideas are the same: we enter data into a database, and we retrieve data from a database. And then a whole slew of other technologies are added to present the data in a user-friendly way: HTML, CSS, and JavaScript.

Integrated library systems (ILS) also provide multiple modules for patron management, acquisitions, circulation, cataloging, serials management, authorities, reporting, and so forth (see Koha: About]. All of those modules rely on some kind of underlying relational database, like MySQL (which is what Koha uses). And this results in a complex, interconnected set of tables. We are working with only one table in our database, the books table. In reality, an ILS will rely on dozens of tables.

In the prior section, we created a MySQL database called opacdb. That database has one table, called books. Then we created a file that used PHP to retrieve the data from the books table and present it on a web page.

In this section, we are going to use different PHP code that will allow us to search the books table and retrieve results based on our search query. In this way, we are more closely mimicking an OPAC, even though we're still far from creating anything that's full fledged.

Creating the HTML Page and a PHP Search Page

The first thing we do is create a basic HTML page that contains a form for entering queries. We'll call this HTML page with the form opacbb.html (just a made up name). When a user clicks on the submit button in the form, the form will activate a PHP script called search.php. That search.php will establish a connection to the OPAC database that we already have created. Our PHP script will contain a special MySQL query that will allow us to search all the fields in our books table. The it will iterate through each row of the books table and return results that match our query. We also add two date fields to our form to limit results by publication dates, which we labeled as copyright in our MySQL books table.


Here is the HTML for our search page:

<title>MySQL Server Example</title>

<h1>A Basic OPAC</h1>

<p>In the form below,
<b>optionally</b> enter text in the search field.
You can search by author, title, or publisher.
Capitalization is not necessary.
It's okay to enter partial information,
like part of an author's, title's, or publisher's name.</p>

<p>The date fields are <b>required</b>.
You can use the date fields to limit results.
I added some extra records,
which you can view to know what you can query:</p>

<p><a href=""></a></p>

<p>This is very much a toy, stripped down OPAC.
The records are basic.
Not only do they not conform to MARC,
but they don't even conform to something
as simple as Dublin Core.
I also don't provide options
to select different fields,
like author, title, or publisher fields.
Instead the search field below searches
all the fields in our <b>books</b> table.
The key idea is to get a sense,
an intuition, of how an OPAC works, though.</p>

<h2>My Basic Library OPAC</h2>
<form method="post" action="search.php">
    <label for="search">Search:</label>
    <input type="text" name="search" id="search">
    <label for="start_date">Start Date:</label>
    <input type="date" name="start_date" id="start_date">
    <label for="end_date">End Date:</label>
    <input type="date" name="end_date" id="end_date">
    <input type="submit" value="Search">


PHP Search Script

Here is the PHP for our search script:

// Load MySQL credentials
require_once 'login.php';

// Establish connection
$conn = mysqli_connect($db_hostname, $db_username, $db_password) or
  die("Unable to connect");

// Open database
mysqli_select_db($conn, $db_database) or
  die("Could not open database '$db_database'");

// Check if search query was submitted
if (isset($_POST['search'])) {
    // Sanitize user input to prevent SQL injection attacks
    $search = mysqli_real_escape_string($conn, $_POST['search']);

    // Get the start and end dates for the date range
    $start_date = mysqli_real_escape_string($conn, $_POST['start_date']);
    $end_date = mysqli_real_escape_string($conn, $_POST['end_date']);

    // Build the MySQL query with a WHERE
    // clause that includes the date range filter
    $query = "SELECT * FROM books WHERE
	    (author LIKE '%$search%' OR
		title LIKE '%$search%' OR
		publisher LIKE '%$search%') AND
		copyright BETWEEN '$start_date' AND '$end_date'";

    // Execute the query
    $result = mysqli_query($conn, $query);

    // Check if any results were returned
    if (mysqli_num_rows($result) > 0) {
        // Loop through the results and output them
        while ($row = mysqli_fetch_assoc($result)) {
            echo "ID: " . $row["id"] . "<br>";
            echo "Author: " . $row["author"] . "<br>";
            echo "Title: " . $row["title"] . "<br>";
            echo "Publisher: " . $row["publisher"] . "<br>";
            echo "Copyright: " . $row["copyright"] . "<br><br>";
    } else {
        echo "No results found.";

    // Free up memory by closing the MySQL result set

// Close the MySQL connection

echo "<p>Return to search page: <a href=''></a></p>";



Replace my IP address ( above with your IP address. Add more records, using MySQL, to your books table, and test your queries.

To add records to your books table, recall that we used the insert into MySQL statements. Here's the example from the prior lesson. Use it to add titles that are of interest to you.

First connect to the MySQL server:

mysql -u opacuser -p

Then run the insert command with the data for the new records:

insert into books
(author, title, publisher, copyright) values
('Emma Donoghue', 'Room', 'Little, Brown \& Company', '2010-08-06'),
('Zadie Smith', 'White Teeth', 'Hamish Hamilton', '2000-01-27');


In this lesson, we created a very bare bones OPAC simply to express the fundamental idea of how data is stored and retrieved on the web. In reality, what separates an OPAC, or a discovery service in a modern integrated library system or library service platform, from other databases on the web is the structure of the records that are stored in the relational database. Such records are structured using MARC. Our records are very simply structured, but still, I hope this helps in creating an intuition about how OPACs and like function.

Creating a Bare Bones Cataloging Module

If you have worked with an integrated library system (or took my electronic resource management class), then you know that an OPAC is simply one module out of several that makeup an integrated library system (ILS). Integrated library systems, and the newer library service platforms (LSP), provide other modules for other types of work. These include modules for acquisitions, authority files, circulation, course reserves, patron management, and more.

In this section, we are going to create a bare bones cataloging module in the same kind of way that we created a bare bones OPAC. Up until this point, you have been adding records to your OPAC using the MySQL command interface. But unless you are a full time database administrator or programmer, it's unlikely that you would add data to your system via that interface. Instead you would use a fancy graphical user interface, which is what integrated library systems provide. The reason we started off with MySQL is not because you would necessarily use this interface on a daily basis. Rather, it's because I want you to understand the foundations of these technologies.

Creating the HTML Page and a PHP Cataloging Page

Like in the last excerise, the first thing we do is create a basic HTML page that contains a form for entering our bibliographic data. Again, our cataloging module will not be real world like. The goal here is to build an intuition about how these technologies work and to also provide some grounding if you do want to pursue a more technical path.

The form that we will create also needs to mirror the data structure in the books table that we created in our prior lesson. That means it will only contain four fields:

  • author
  • title
  • publisher
  • copyright

I'll call this page index.html. I'll create a new directory for this module:

cd /var/www/html
sudo mkdir cataloging

Then I'll use nano to create the index.html file and add the content:

cd cataloging
sudo nano index.html

In index.html, we add the following content:

<!DOCTYPE html>
	<title>Enter Records</title>
	<h1>OPAC Library Administration</h1>

	<p>This is the library administration page for entering records into the OPAC.</p>
	<p>Please do not use this page unless you are an authorized cataloger.</p>

	<form action="insert.php" method="post">
		<label for="author">Author:</label>
		<input type="text" name="author" id="author" required><br><br>

		<label for="title">Book Title:</label>
		<input type="text" name="title" id="title" required><br><br>

		<label for="publisher">Publisher:</label>
		<input type="text" name="publisher" id="publisher" required><br><br>

		<label for="copyright">Copyright:</label>
		<input type="date" id="copyright" name="copyright">

		<input type="submit" value="Submit">

PHP Insert Script

The index.html page will provide a user interface, that is, a form, for entering our bibliographic data. However, the PHP script is needed to communicate and add the data from our form into our MySQL database and books table.

Also, just as the HTML form has to match the data structure of the books table, the PHP script also needs to match the form from the HTML page and the data structure in the books table.

Here is the PHP script, which I call insert.php:


// Load MySQL credentials
require_once '../login.php';

// Establish connection
$conn = mysqli_connect($db_hostname, $db_username, $db_password) or
  die("Unable to connect");

// Open database
mysqli_select_db($conn, $db_database) or
  die("Could not open database '$db_database'");

// Prepare and bind SQL statement
$stmt = $conn->prepare("INSERT INTO books (author, title, publisher, copyright) VALUES (?, ?, ?, ?)");
$stmt->bind_param("ssss", $author, $title, $publisher, $copyright);

// Set parameters and execute statement
$author = $_POST["author"];
$title = $_POST["title"];
$publisher = $_POST["publisher"];
$copyright = $_POST["copyright"];

if ($stmt->execute() === TRUE) {
    echo "New record created successfully";
} else {
    echo "Error: " . $stmt->error;

// Close statement and connection

echo "<p>Return to the cataloging page: <a href=''></a></p>";


Since our HTML and PHP files allow us to enter data into our MySQL database from a simple web interface, we need to limit access to the module. Again, in a real-world situation, modules like these would have a variety of security measures in place to prevent wrongful data entry. In our case, we will rely on a simple authorization mechanism provided by the Apache2 server called htpasswd.

First, we create an authentication file in our /etc/apache2 directory, which is where the Apache2 web server stores its configuration files. The file will contain a hashed password and a username we give it. In the following command, I set the username to libcat, but it could be anything:

sudo htpasswd -c /etc/apache2/.htpasswd libcat

Next we need to tell the Apache2 web server that we will use the htpasswd to control access to our cataloging module. To do that, we use nano to open the apache2.conf file. We need

sudo nano /etc/apache2/apache2.conf

In the apache2.conf file, look for the following code block / stanza. We are interested in the third line in the stanza, which is line 173 for me, and probably is for you, too.

<Directory /var/www/>
  Options Indexes FollowSymLinks
  AllowOverride None
  Require all granted

Carefully, we need to change the word None to the word All:

<Directory /var/www/>
  Options Indexes FollowSymLinks
  AllowOverride All
  Require all granted

Next, change to the cataloging directory and use nano to create a file called .htaccess (note the leading period):

cd /var/www/html/cataloging
sudo nano .htaccess

Add the following content to .htaccess:

AuthType Basic
AuthName "Authorization Required"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user

Check that the configuration file is okay:

apachectl configtest

If you get a Syntax OK message, then restart Apache2 and check its status:

sudo systemctl restart apache2
systemctl status apache2

Now visit your cataloging module. You should be required to enter the username and password that you created with htpasswd.


In the last lesson, we created a very bare bones OPAC that would allow patrons to search our catalog. In this lesson, we learned how to create a very bare bones cataloging module that would allow librarians to add bibliographic data and records to our OPAC.

Add some records using the above form, and then return to your OPAC and conduct some queries to confirm that the new records have been added.

You can also use the MySQL command line interface to view the new records, just like we did a couple of lessons ago.

In a production level environment, we would add quite a bit more. Our MySQL database would contain many more tables that allow storing data related to the modules listed above. We would also like to make our modules graphically attractive and provide more content. That would mean we would add Cascading Style Sheets (CSS) and JavaScript to create an attractive and usable interface. But that would be a whole other class.

Install WordPress


WordPress is a free and open source content management system (CMS). Originally, its focus was on providing a platform for blogging, but throughout the last decade plus, it has become a general purpose CMS that can serve as a website builder. Two sites exist to provide access to WordPress: and is a hosting solution, which means that customers can sign up and create a free WordPress site. Since its hosted, customers are only responsible for their content and not for managing the WordPress installation and its updates. Various paid plans can extend the functionality offered to customers. is maintained by the WordPress Foundation, which oversees the development of and provides access to the WordPress software. When we download the WordPress software, we download it from Unlike the hosted solution, when we install and setup WordPress on our own servers, we become responsible for administrating its installation and for keeping the software updated.

WordPress is widely used software, and because of that, it's often the focus of attack. Take a moment to read about the developers's efforts to protect WordPress: Security. We will not need to update our WordPress installs during the course of this course, but you should be familiar with the update process in case you decide to maintain your install or an install at a future date: Updating WordPress.

Libraries and WordPress

Many libraries use WordPress as as their main website and a quick web search will reveal them. For example, I quickly found an example of a (beautiful) WordPress library site for the Reading Public Library (RPL) in Massachusetts. These library websites coordinate with additional solutions that provide integrated library systems and other electronic resource services. RPL, for instance, connects their WordPress installation, which serves as their main website page, with the open source Evergreen ILS, which serves their OPAC. Check this by clicking on RPL's Library Catalog link, and you will see that it takes you to a different URL.

Aside: it is this need to coordinate so many services across all these websites that in part drives the need to develop standards for data exchange and work flow processes. For those of you have taken my electronic resource management course, you will recall we spent an entire module on this topic.

Many library websites are partitioned like this. Thus, when we install WordPress soon, it is as if we are only installing the front entrance to the library. Libraries are generally like this. They have one main website (like but then connect to other sites that provide access to OPACS, discovery systems, OverDrive or other eBook vendors, bibliographic databases, and more. This is part of the confusion around how libraries provide electronic resources. There are efforts to make all these components connect more seamlessly (e.g., through discovery systems), but if we were to model this to the walking around world, it would be like having a library that has multiple buildings, where each building provides one thing: one building for books, one building for journals, another building for other journals, another building for another set of journals, another building for looking up where to find journals, another building for special collections, and so on. I digress.

You can read the announcement about RPL's WordPress launch at: Reading Public Library Launches New WordPress Site. The above announcement page also describes how various plugins were used to offer patrons additional functionality. These include plugins to display business hours and to manage events and event attendees. Plugins are often used with WordPress sites to offer all sorts of additional capabilities. Currently, there are over 60 thousand plugins available for WordPress, but some are of higher quality and utility than others. In addition to the thousands of available plugins, there are over 10 thousand free themes for WordPress sites. Plus, many businesses offer paid themes or can offer customized themes based on customer needs. These themes can drastically alter the appearance and usability of a WordPress site.


So far I have shown you how to install software using two methods:

  • using the apt command
  • downloading from GitHub

In this lesson, we are going to install WordPress by downloading the most recent version from and installing it manually. The WordPress application is available via the apt command, but the apt process makes it a bit more confusing than it should be, oddly.

We are going to kind of follow the documentation provided by You should read through the documentation before following my instructions, but then follow the process I outline here instead because the documentation uses some different tools than we'll use.

Another reason we do this manually is because it builds on what we have learned by building our bare bones ILS. That is, the two processes are similar. In both cases, we create a specific database for our platform, we create a specific user for that database, and we provide login credentials in a specific file.

First, read through but don't follow the following instructions:

How to install WordPress

Customized Installation Process

After you have read through the documentation, follow the steps below to complete the manual install:

Step 1: Requirements

All major software has dependencies. For example, our bare bones OPAC depends on MySQL and PHP to provide the database (MySQL) and the glue (PHP) between our HTML and the database. The same is true for WordPress. However, since WordPress is much more complicated software than our bare bones OPAC, its dependencies are stricter. This means that when we plan to download software outside of the apt ecosystem, we need to make sure that our systems meet the requirements for our installation. The Requirements page states that the WordPress installation requires at least PHP version 7.4 and MySQL version 5.7. We can check that our systems meet these requirements with the following commands:

php --version
mysql --version

The output from php --version shows that our systems have PHP 7.4.3, which is greater than PHP 7.4. The output from mysql --version show that our systems have MySQL 8.0, which is greater than MySQL 5.7. This means we can proceed.

Next, we need to add some additional PHP modules to our system to let WordPress operate at full functionality. We can install these using the apt command:

sudo apt install php-curl php-xml php-imagick php-mbstring php-zip php-intl

Then restart Apache2 and MySQL:

sudo systemctl restart apache2
sudo systemctl restart mysql

Step 2: Download and Extract

The next step is to download and extract the WordPress software, which is downloaded as a tar.gz file. This is very much like a compressed zip file. Although we only download one file, when we extract it with the tar command, the extraction will result in a new directory that contains multiple files and subdirectories. The general instructions include:

  1. Change to the /var/www/html directory.
  2. Download the latest version of WordPress using the wget program.
  3. Extract the package using the tar program.

Specifically, we do the following on the command line:

cd /var/www/html
sudo wget
sudo tar -xzvf latest.tar.gz

As noted in the WordPress documentation, this will create a directory called wordpress in the same directory. Therefore the full path of your installation will located at /var/www/html/wordpress

Step 3: Create the Database and a User

The WordPress documentation describes how to use phpMyAdmin to create the database and a user for WordPress. phpMyAdmin is a graphical front end to the MySQL relational database that you would access through the browser. But I like to minimize the software that we install on servers to reduce the server's security exposure. Therefore, we are going to create the WordPress database and a database user using the same process we used to create a database and user for our bare bones OPAC. The general instructions are:

  1. Switch to the root Linux user
  2. Login as the MySQL root user

Specifically, we do the following on the command line:

sudo su
mysql -u root

The mysql -u root command places us in the MySQL command prompt. The next general instructions are to:

  1. Create a new user for the WordPress database
  2. Be sure to replace the Xs with a strong password
  3. Create a new database for WordPress
  4. Grant all privileges to the new user for the new database
  5. Examine the output
  6. Exit the MySQL prompt

Specifically, this means the following (be sure to replaces the Xs with a unique and strong password of your own):

create user 'wordpress'@'localhost' identified by 'XXXXXXXXX';
create database wordpress;
grant all privileges on wordpress.* to 'wordpress'@'localhost';
show databases;

Step 4: Set up wp-config.php

When we created our bare bones OPAC, we created a file called login.php that contained the name of the database (e.g., opacdb), the name of the database user (e.g., opacuser), and the user's password. WordPress follows a similar process, but instead of login.php, it uses a file called wp-config.php.

Follow these general steps:

  1. Change to the wordpress directory, if you haven't already.
  2. Copy and rename the wp-config-sample.php file to wp-config.php.
  3. Edit the file and add your WordPress database name, user name, and password in the fields for DB_NAME, DB_USER, and DB_PASSWORD.

This means that we specifically do the following:

cd /var/www/html/wordpress
sudo cp wp-config-sample.php wp-config.php
sudo nano wp-config.php

In nano, add your database name, user, and password in the appropriate fields, just like we did with our login.php file for our bare bones OPAC.

Additionall, we want to disable FTP uploads to the site. To do that, navigate to the end of the file and add the following line:


Step 5: Optional

The WordPress files were installed at /var/www/html/wordpress. This means that your site would be located at:

If you want to, you can rename your wordpress directory to something else. The WordPress documentation uses blog as an example. But it could be something else, like the name of a fictional library that you might be using WordPress to build a site. If you decide to change it, be sure to keep the name lowercase and one word (no spaces and only alphabetic characters). For example, if I want to change mine to blog, then:

cd /var/www/html
sudo mv wordpress blog

Step 6: Change File Ownership

WordPress will need to write to files in the base directory. Assuming your still in your base directory, whether that is /var/www/html/wordpress or /var/www/html/blog or like, run the following command:

sudo chown -R www-data:www-data *

Step 7: Run the Install Script

The next part of the process takes place in the browser. The location (URL) that you visit in the browser depends on your specific IP address and also includes the directory in /var/www/html that we extracted WordPress to or that you renamed if you followed Step 5. Thus, if my IP address is and I renamed by directory to blog, then I need to visit the following URL:

IF I kept the directory named wordpress, then this is the URL that I use:

Finishing installation

From this point forward, the steps to complete the installation are exactly the steps you follow using WordPress's documentation.

Most importantly, you should see a Welcome screen where you enter your site's information. The site Username and Password should not be the same as the username and password you used to create your WordPress database in MySQL. Rather, the username and password you enter here are for WordPress users; i.e., those who will add content and manage the website.

Two things to note:

We have not setup Email on our servers. It's actually quite complicated to setup an email server correctly and securely, but it wouldn't work well without having a domain name setup anyway. So know that you probably should enter an email when setting up the user account, but it won't work.

Second, when visiting your site, your browser may throw an error. Make sure that the URL is set to http and that it's not trying to access https. Setting up an https site also generally requires a domain name, but we are not doing that here. So if there are any problems accessing your site in the browser, be sure to check that the URL starts off with http.


Congrats on setting up your WordPress library site. It's now time to explore and build a website. Use free themes and free plugins to alter the look of the site, its usability, and its functionality. Try to create a nice looking website. Generally, your goal for the next week is to create an attractive, yet fictional, front entrance for a library website. It's also a break from the command line!

Install Omeka

Omeka is an "Open-source web publishing platforms for sharing digital collections and creating media-rich online exhibits." Most if not all of you have already used Omeka in a prior course. Here our task is not to learn information/knowledge organization, per se, but to learn how to administer the Omeka digital library platform.

The Task

So far we have created our own bare bones OPAC/ILS and we have downloaded, installed, and configured WordPress on our servers. We will use the same basic process to download, install, and configure Omeka.

However, instead of providing comprehensive instructions, your goal is to take what you learned from the bare bones OPAC/ILS and WordPress assignments, and apply them to the Omeka installation and setup. Below are some additional prerequisites that you should complete first. After you've completed them, move on to the General Steps section to remind yourself of the overall process.

You can do it! Be sure to ask and discuss on our chat server.


When we installed WordPress, we installed most of the prerequisites that Omeka needs, but there are a couple of additional things we need to do.

Some prerequisites:

  • Install ImageMagick: this is a suite of utilities to work with photo files. It's used by Omeka to create thumbnail images of any photo uploaded to the digital library. See Imagemagick for more information.
sudo apt install imagemagick
  • Enable Apache mod_rewrite. This is an Apache module used to rewrite URLs. Omeka uses this to create appropriate URLs for items and collections in its digital libraries.
sudo a2enmod rewrite

You should be instructed to restart Apache after enabling rewrite:

sudo systemctl restart apache2

General Steps

You have already completed all the steps below when you created a bare bones OPAC/ILS and installed WordPress. Your task is to apply what you've learned by completing an Omeka installation on your own. (You can work together and discuss on our chat server.)

Note that the process is very similar to what we have already done with our bare bones OPAC/ILS and our WordPress installations. Use this handbook to remind you of the specific commands. In short, you are going to complete the following steps:

  • Create a new user and a new database in MySQL for the Omeka installation (do not re-use the WordPress database, user, or credentials).
  • Use wget from your server to download Omeka Classic as a Zip file and extract it in /var/www/html:
    • unzip it with the unzip command, which you will have to install with the apt command.
    • the extracted directory will be named omeka-3.1. You might want to rename it simply omeka.
  • In the extracted directory, find the db.ini file and add your database credentials, and replace all values containing XXXXXX, with the appropriate information. This is the same thing we did with the login.php file for our bare bones OPAC/ILS and the wp-config.php file for WordPress.
  • Use the chown command like we did with WordPress on the files directory in the omeka directory. The user and owner should again be www-data.
  • Restart Apache2 and MySQL
  • In your web browser, go to http://your-ip-address/omeka/ and complete the setup via the web form, just like you did with WordPress.

The user manual below is helpful, but it does not provide explicit instructions.

Be sure to download Omeka Classic and not Omeka S.

Install the Koha ILS

Koha ILS

Koha is an open source "library management system", otherwise called an integrated library system (ILS). These kinds of systems provide modules that perform specific kinds of functionality. Koha's modules include:

  • Administration
  • Patron management
  • Cash management
  • Circulation
  • Cataloging
  • Course reserves
  • Serials
  • Acquisitions
  • Reports
  • OPAC

According to Library Technology Guides, Koha is installed in "4,040 libraries [around the world], spanning 5,677 facilities or branches". Most installations are in medium sized or small libraries. Koha is well represented in academic libraries, but the majority of installations are in public libraries.

Although Koha is an open source ILS and free to download, install, and administer without external support, librarians can hire companies that support open source library management solutions, like ByWater Solutions or the Equinox Open Library Initiative These companies support ILS migration, hosting, training, and more. They also provide support for other library software services, such as open source discovery systems and electronic resource management systems.

In addition to Koha, Evergreen is also an open source integrated library system. According to Library Technology Guides, Evergreen is primarily installed at small and medium size public libraries, and most installations are in the U.S. and Canada.

There is currently a migration to what has been called library service platforms (LSP) in recent years. The LSP is a next generation ILS that is designed from the start to integrate electronic resources. For example, the ILS has an OPAC which was designed to search a library's print collections. Modern OPACs have been adapted for electronic resources, but they are still limited because of the older design model. LSPs use a discovery service instead of an OPAC. Discovery services are designed to search a library's entire collection, including the content in third party databases and journals. Example LSPs include Ex Libris Primo (used by UK Libraries), OCLC's WorldCat Discovery Service, and open source solutions like Aspen Discovery and VuFind.

It is probably unnecessary to state that integration of library systems like the ILS and the LSP is a major part of modern libraries. When we visit a library's website, we will first interact with a normal website that might be built on WordPress, Drupal, or some other content management system. But these websites will link to the public facing components of an ILS or LSP, as well as other services, such as bibliographic database, journal publishers, ebook services, and more. It may therefore be the systems librarians job to help build and connect these services. In this demo, we will continue that work by installing, configuring, and setting up the Koha ILS.

Google Cloud Setup

Before we begin to install Koha, we need to create a new virtual machine instance and configure the Google firewall to allow HTTP traffic to our Koha install.

New Virtual Instance

The virtual instance we have been using does not meet the memory (RAM) needs required by the Koha integrated library system. We therefore need to create a new virtual instance that has more RAM. As a refresher, see the section titled gcloud VM Instance at Using gcloud Virtual Machines. However, we will modify the Series to E2 and set the Machine Type to 2 vCPU, 4 GB memory. All else, including the operating system (Ubuntu 20.04), should remain the same. Note that this is a more expensive setup. Therefore, feel free to delete this instance at the end of the semester.

Google Cloud firewall

Later, after we install Koha, we will need to access the staff interface on a special HTTP port. HTTP (i.e., web) traffic is delivered through what are called ports. The default port for HTTP is 80, and the default port for HTTPS is 443. Since we do not have encryption enabled, this means that the Apache2 web server listens on port 80 by default for all web traffic. Firewalls are used to control incoming and outcoming traffic via ports. When we selected Allow HTTP traffic when we created our virtual instance, we instructed the Google Console firewall to allow traffic through port 80. We need to add a firewall rule to allow web traffic through port 8080. We will use port 8080 to access the Koha staff interface.

Please take a moment to read more about ports: What is a computer port? | Ports in networking.

To create a firewall rule to allow traffic to port 8080, go to the Google Cloud Console:

  • Click on the hamburger ☰ icon at the top left.
  • Click on VPN Network
  • Click on Firewall
  • At the top of the page, choose Create a firewall rule (do not choose Create a firewall policy)
    • Add name: koha
    • Add description: open port 8080
  • Next to Targets, click on All instances in the network
  • In the Source IPv4 ranges, add
  • Click on Specified protocols and ports
    • Click on TCP
    • Add 8080 in the Ports box
  • Click on Create

Install Koha Repo

Server setup

Now let's log onto our new server and prepare it for the Koha installation.

First we need to update our local repositories:

sudo apt update

And then upgrade our servers:

sudo apt upgrade

The next two commands help save disk space. The apt autoremove command "is used to remove packages that were automatically installed to satisfy dependencies for other packages and are now no longer needed as dependencies changed or the package(s) needing them were removed in the meantime" (see man apt). The apt clean command "clears out the local repository of retrieved package files" (see man apt-get). In the following example, I combine both commands on one line:

sudo apt autoremove -y && sudo apt clean

Next we need to install gnupg2, which is used to create digital signatures, encrypt data, and aid in secure communication.

sudo apt install gnupg2

At the time of this demo, the update above downloaded a new Linux kernel. Using the new kernel requires a reboot. The reboot command will disconnect you from the server. Just wait a minute or so and then re-connect.

sudo reboot now

Add Koha Repository

When you run the sudo apt update command, Ubuntu syncs the local repository database with several remote repositories. These remote repositories contain metadata about the packages they contain. The syncing process identifies if any new software updates are available. The remote repositories are also used to retrieve software.

We can add repositories to sync with and to use to download software, and this includes the Koha ILS. To add the special Koha repository to our system, we use the following command:

Most of the following commands require administrator access. Therefore, I will login as the root user to make it a bit easier. If you do not log in as the root user, be sure to use the sudo command.

sudo su

Add the Koha repository to our server:

echo 'deb stable main' | sudo tee /etc/apt/sources.list.d/koha.list

We then add the digital signature that verifies the above repo:

wget -q -O- | sudo apt-key add -

Install Koha

Next we need to update/sync the new repository with the Koha remote repository. This just means that we use apt update again.

apt update

Now we view the package information for Koha:

apt show koha-common

And install it:

apt install koha-common

The above command will download and install a lot of additional software, and therefore the process will take several minutes.

Configure Koha

Next we need to edit some configuration files for Koha:

nano /etc/koha/koha-sites.conf

In the above koha-sites.conf file, change the line that contains the following information:




Next install and setup mysql-server:

apt install mysql-server

Next we set the root MySQL password:

mysqladmin -u root password bibliolib1

When we installed Koha, the Apache2 web server was installed with it as a prerequisite. We need to enable URL rewriting and CGI functionality.

a2enmod rewrite
a2enmod cgi 

Now we need to restart Apache2 in the normal way:

systemctl restart apache2

Next we create a database for Koha:

koha-create --create-db bibliolib

We need to tell Apache2 to listen on port 8080:

nano /etc/apache2/ports.conf 

And add:

Listen 8080

Make sure Apache configuration changes are valid:

apachectl configtest

If you get an error message, trace the error in the file and line listed.

Let's restart Apache2.

systemctl restart apache2

We'll disable the default Apache2 setup, enable traffic compression using deflate, enable the bibliolib site, and then reload Apache2's configurations and restart again:

a2dissite 000-default
a2enmod deflate
a2ensite bibliolib
systemctl reload apache2
systemctl restart apache2

Koha Web Installer

All the backend work is complete, and like we did with WordPress and Omeka, we can complete the installation through a web installer.

First, get Koha username and password in the following file:

nano /etc/koha/sites/bibliolib/koha-conf.xml

Look for the <config> stanza (line number 252) and the line beginning with <user> (line number 257). The password is on the line after (line number 258).

Make sure your URL begins with http* and not https, and visit the web installer at:


The documentation for the web installer is helpful. One thing to do is to add sample libraries and sample patrons. More generally, be sure to follow instructions as you click through each step.

Introduction to the Koha installation process

Public OPAC

When the install and setup are complete, you will have access to the staff interface. To view the public facing OPAC, you need to make a setting change.

  • Click on More in the top drop down box
  • Click on Administration
  • Click on Global System Preferences
  • Click on OPAC in the left hand side bar
  • Scroll down to the OPACBaseURL line.
  • Enter the IP address of your server: http://IP-ADDRESS
  • Click on Save all OPAC Preferences

Once you save these preferences, you should be able to visit your public facing OPAC at the server IP address.

Additional Tasks

Once you've installed and setup Koha, begin to learn the system. Some example tasks:

  • Create patron accounts
  • Create bibliographic records
  • Check out books to patrons
  • Delete patron circulation history


In this final section, you learned how to install and setup a Koha ILS installation on a Linux server.


Helpful documentation and demos:



In this course, we learned how to:

  • work with the Google Cloud console
  • install and setup a new Ubuntu Linux server
  • use the Linux command line
  • use a command line text editor
  • search text
  • install and manage software
  • use Git and GitHub
  • build a LAMP server
  • create a barebones integrated library system
  • install and configure WordPress, Omeka, and Koha sites
  • connect these sites to create a full library web presence