There are a lot of different methods, but a good starting point to understand how this might be done is the method of steepest descent. First we take the generalised eigenvalue expression you cite and rearrange to express the energy expectation value as
$$E=\frac{\phi^\dagger \mathrm{H}\phi}{\phi^\dagger \mathrm{S}\phi},$$
where I've generalised to allow complex wavefunctions for completeness, so the Hermitian conjugate (denoted by $\dagger$) has replaced the transpose in your expression.
The variational principle tells us that the ground-state energy we seek is the minimum possible value of this expectation value. If we start with some trial $\phi$ and compute the energy expectation value, we may also ask how this expectation value would change if we made a small change to $\phi$. Differentiating the expectation value with respect to $\phi$ using the quotient rule (where the matrix-derivative here may be interpreted as being element-wise) we obtain:
$$
\begin{array}{cl}
\frac{\delta E}{\delta \phi^\dagger} &= \frac{\left(\phi^\dagger \mathrm{S}\phi\right)\mathrm{H}\phi - \left(\phi^\dagger \mathrm{H}\phi\right)\mathrm{S}\phi}{\left(\phi^\dagger \mathrm{S}\phi\right)^2}\\
&= \frac{\mathrm{H}\phi - E\mathrm{S}\phi}{\phi^\dagger \mathrm{S}\phi}.
\end{array}
$$
If we assume that $\phi$ is S-orthonormalised, such that $\phi^\dagger \mathrm{S}\phi=I$ (where $I$ is the identity) then we can write this more compactly as
$$
\begin{array}{cl}
\frac{\delta E}{\delta \phi^\dagger} &= \mathrm{H}\phi - E\mathrm{S}\phi.
\end{array}
$$
This expression tells us the direction in which to change $\phi^\dagger$ in order to increase $E$ most rapidly; since we wish to decrease $E$, we should change $\phi^\dagger$ in the opposite direction.
Now at this point I should note that we don't actually want to change $\phi^\dagger$, we want to change $\phi$ and there's a complication here which arises from the fact that this is a generalised eigenvalue problem. The gradient I've derived is covariant (it transforms like $S\phi$ under a change of basis), and we need a contravariant quantity (transforms like $\phi$ under a change of basis) if we're going to use it to update $\phi$. There are several avenues for getting this, but probably the simplest and most computationally efficient is to pre-multiply by $S^{-1}$.
We may now define a direction,
$$D = -S^{-1}\frac{\delta E}{\delta \phi^\dagger} = -S^{-1}\mathrm{H}\phi - E\phi,$$
in your example above, there are two ways in which we may change $\phi$: we can change $C$; and we can change $\alpha$. Our search direction $D$ contains changes to both,
$$
\begin{array}{rl}
D = \left(\begin{array}{c}
D_C\\
D_\alpha
\end{array}\right)
&= -\left(\begin{array}{c}
\frac{\delta E}{\delta C^\dagger}\\
\frac{\delta E}{\delta \alpha}
\end{array}\right)\\
&= -\frac{\delta E}{\delta \phi^\dagger}\left(\begin{array}{c}
\frac{\delta \phi^\dagger}{\delta C^\dagger}\\
\frac{\delta \phi^\dagger}{\delta \alpha}\\
\end{array}\right)\\
&= -(H-ES)\phi\left(\begin{array}{c}
\frac{\delta \phi^\dagger}{\delta C^\dagger}\\
\frac{\delta \phi^\dagger}{\delta \alpha}
\end{array}\right)
\end{array}
$$
We may now search along the direction $D$ for an improved estimate of the ground state $\phi$. The simplest approach is to use a line-search method, whereby we define
$$\phi^\prime (\lambda) = \phi + \lambda D$$
by which we mean
$$
\left(\begin{array}{c}
C^\prime(\lambda)\\
\alpha^\prime(\lambda)
\end{array}\right)
= \left(\begin{array}{c}
C\\
\alpha
\end{array}\right)
+\lambda \left(\begin{array}{c}
D_C\\
D_\alpha
\end{array}\right)
$$
Now we find the minimum expectation value of the energy with respect to $\lambda$ (a 1D minimisation problem, so fairly straightforward). Note that the choice of function of $\lambda$ above means that $\phi^\prime$ is not orthonormalised in general, even if $\phi$ and $D$ are, which necessitates re-orthonormalisation later on. More sophisticated methods are available which do not have this side-effect.
Once we have the value of $\lambda$ which minimises the energy expectation value, $\lambda_{opt}$, we have an improved estimate of the ground state $\phi^{new}=\phi(\lambda_{opt})$. We may now compute the energy derivative about $\phi^{new}$, and hence a new search direction, and the procedure repeats.
There is a complication in that the sensitivity to changes in $C$ and $\alpha$ will be very different, leading to ill-conditioning; this can be resolved by "preconditioning" the search direction (see later on).
This iterative update procedure is usually terminated when the change in solution falls below some tolerance criterion -- the change usually being measured by the change in the energy expectation value or the magnitude of the gradient.
This method is relatively crude and only performs well when the expectation values associated with the underlying basis states are similar; if this is not satisfied, then the problem becomes ill-conditioned and can take many iterations to converge (it may even diverge).
The conditioning is dependent on the curvature of the energy expectation with respect to $\phi^\dagger$, and if we knew what that was we could compute an improved search direction (what you do is pre-multiply the gradient by the inverse of the curvature tensor). Unfortunately in electronic structure calculations we don't usually know what the curvature is analytically, and it's very expensive to compute. However, two practical improvements are:
- Preconditioning -- premultiply the gradient by an approximation to the inverse curvature; in the case of electronic structure calculations this would often be based on parts of the Hamiltonian which dominate in particular regimes, for example the work of Teter, Payne and Allan (https://doi.org/10.1103/PhysRevB.40.12255)
- Quasi-Newton method -- essentially, use gradient information from previous iterations to estimate the curvature and produce an improved search direction; examples include the popular conjugate gradients and (L-)BFGS methods.
These two approaches may be combined, and preconditioned quasi-Newton methods can be extremely efficient. Quasi-Newton methods are fairly standard across optimisation problems and you'll see the same methods cropping up time and time again; in contrast, finding a good preconditioning approach will require careful thought about the behaviour of your particular problem, so different approaches are employed in different domains.